POJ1011
Description
George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.
问题:不知道原长和不知道木棍的数量,从L*N的木棍里切除了一堆小木棍(长度一样的小木棍可能很多)
分析1:从里面选最大木棍,假设它现在是原长。如果选最小的木棍必定无法涵盖最大木棍。(这一步需要对木棍从大到小排序)
分析2:假设的原长(说它是length),如果length无法整除sum,说明有剩的多余的木棍,所以这不是原长。(这一步length++)
分析3:(剪枝+遍历)如果现在探索的原长(既cur)是0,那么就得从小木棍里面选最长的,并记录已经走过这个木棍,用过这个木棍(x++)(if(cur==0))
分析4:(剪枝+遍历)从当前没走过的最大的小木棍开始,往更小的木棍开始,跳过原先走过且数值一样的木棍,加没有超过length的小木棍到里面,然后更新cur
分析5:(剪枝+遍历)如果cur==length,而且所有的小木棍都走过了,说明这就是原长,跳出
以上就是分析过程
now,自己写糊了几遍(md真的手残),看了别人的代码,再找到错误,再改后:
#include <iostream> #include<cstdlib> #include<cstdio> #include<stack> #include<algorithm> #include<cstring> using namespace std; int n,flag=0; int stick[10000],k[10000]; int length,sum=0; bool cmp(int a,int b){ return a>b; } void dfs(int cur,int x,int w){ if(flag) return; if(cur==0){ int m=0; while(k[m])m++; k[m]=1; dfs(stick[m],x+1,m+1); k[m]=0; return; } if(cur==length){ if(x==n){ flag=1; }else{ dfs(0,x,0); } return; } for(int i=w;i<n;i++) if(!k[i]&&cur+stick[i]<=length){ if(!k[i-1]&&stick[i-1]==stick[i]){ continue; } k[i]=1; dfs(cur+stick[i],x+1,i+1); k[i]=0; } } int main(){ while(scanf("%d",&n)&&n){ memset(stick,0,sizeof(stick)); sum=0; flag=0; for(int i=0;i<n;i++){ scanf("%d",&stick[i]); sum+=stick[i]; } sort(stick,stick+n,cmp); for(length=stick[0];length<sum;length++){ if(sum%length==0){ memset(k,0,sizeof(k)); dfs(0,0,0); if(flag) break; } } printf("%d\n",length); } return 0; }

浙公网安备 33010602011771号