问题描述:有一个由很多木棒构成的集合,每个木棒有对应的长度,请问能否用集合中的这些木棒以某个顺序首尾相连构成一个面积大于 0 的简单多边形且所有木棒都要用上,简单多边形即不会自交的多边形。
初始集合是空的,有两种操作,要么给集合添加一个长度为 L 的木棒,要么删去集合中已经有的某个木棒。每次操作结束后你都需要告知是否能用集合中的这些木棒构成一个简单多边形。
输入描述:每组测试用例仅包含一组数据,每组数据第一行为一个正整数 n 表示操作的数量(1 ≤ n ≤ 50000) , 接下来有n行,每行第一个整数为操作类型 i (i ∈ {1,2}),第二个整数为一个长度 L(1 ≤ L ≤ 1,000,000,000)。如果 i=1 代表在集合内插入一个长度为 L 的木棒,如果 i=2 代表删去在集合内的一根长度为 L 的木棒。输入数据保证删除时集合中必定存在长度为 L 的木棒,且任意操作后集合都是非空的。
输出描述:对于每一次操作结束有一次输出,如果集合内的木棒可以构成简单多边形,输出 "Yes" ,否则输出 "No"。
输入例子:
5 1 1 1 1 1 1 2 1 1 2
输出例子:
No No Yes No No
分析:问题的本质其实就是,给定n条边,问能否构成n边形,然而给定n条边,问能否构成n边形的条件是任意n-1条边大于另一条边。因此本题可以从此处着手。
Java代码如下,代码写法比较通用,读者可以很容易转换为其他语言实现:
1 import java.util.*; 2 public class Main { 3 public static boolean panduan(int a[],int n){ //用来判断能够构成n边形 4 boolean flag=true; //先假设可以构成n边形,再去找不能构成的理由 5 if(n<3)return false; //如果少于三条边,那么肯定构不成 6 Arrays.sort(a,0,n); //将木棒按长度进行排序 7 int s=0; 8 for(int j=0;j<n-1;j++) 9 s=s+a[j]; 10 if(s<=a[n-1])flag=false; //用最长的木棒和剩余木棒长度和进行比较即可判断 11 return flag; 12 } 13 public static void main(String[] args) { 14 // TODO 自动生成的方法存根 15 Scanner scan=new Scanner(System.in); 16 while(scan.hasNext()){ 17 int n=scan.nextInt(); //读入n 18 int a[]=new int[n]; //创建一个数组用来存储每条边 19 for(int i=0;i<n;i++) 20 { 21 int caozuo=scan.nextInt(); //操作数,只能是1或2 22 int L=scan.nextInt(); //边长 23 if(caozuo==1)a[i]=L; //如果添加木棒,则正常放入 24 else 25 { 26 for(int j=i-1;j>=0;j--) //如果减少木棒,则将之前和L相等的一条木棒去掉 27 if(a[j]==L){a[j]=0;break;} 28 } 29 if(panduan(a,i+1))System.out.println("Yes"); 30 else System.out.println("No"); 31 } 32 33 } 34 } 35 36 }
输出结果为:
5
1 1
No
1 1
No
1 1
Yes
2 1
No
1 2
No