POJ_1014_Dividing

///动态规划,又有点筛选法的思想,按价值划分状态,要求能否划分出一半的价值也就是求 //value[halfvalue]的状态。 #include<stdio.h> #include<string.h> //保存每一种价值的石头 int num[7]; //value[i]用来指示是否能划分出i的石头出来,1则能划分出来,反之为0。 bool value[100005]; int main() { freopen("divide.in","r",stdin); freopen("ans.txt","w",stdout); int cas=0; while(1) { int i,j,sum=0; for(i=1;i<=6;i++) { scanf("%d",&num[i]); sum+=num[i]*i; } if(!sum) break; cas++; int halfvalue=sum/2; //检查价值之和能否被2整除 if(sum&1) printf("Collection #%d:/nCan't be divided./n/n",cas); else { int t=0,k,end=0,temp; memset(value,0,sizeof(value)); value[0]=1; for(i=1;i<=6;i++) { if(num[i]>0) { //从大到小查找比由小到大更快找到结果,另外也可以避免出现将状态由0变为1后对当前循环的影响 //例如0 0 0 2 2 1就会出现这样的情况 for(j=t;j>=0;j--) { if(value[j]) { for(k=1;k<=num[i];k++) { //如果当前j+k*i大于halfvalue,那么对于k+1,k+2..均大于halfvalue if(j+k*i>halfvalue) break; if(!value[j+k*i]) { value[j+k*i]=1; } //如果value[j+k*i]=1,因j从大到小,所以j+(k+1)*i等等会大于halfvalue或已经为1。 else break; //如果已经划分出halfvalue,则没必要继续,应该退出 if(j+k*i==halfvalue) { end=1;break; } } } if(end)break; } } if(end)break; t+=num[i]*i; if(t>halfvalue)t=halfvalue; } if(value[halfvalue]) printf("Collection #%d:/nCan be divided./n/n",cas); else printf("Collection #%d:/nCan't be divided./n/n",cas); } } return 0; }

你可能感兴趣的:(POJ_1014_Dividing)