题目来源: http://acm.pku.edu.cn/JudgeOnline/problem?id=1011
解题报告:
想了两天, 看了其他的解题报告, 终于稍微想通了一点
具体的思路, 我也说不清楚, 有一份解题报告蛮清楚的, 是: http://blog.csdn.net/woshixingaaa/archive/2010/05/14/5589100.aspx
下面是我的代码:
#include <iostream> #include <algorithm> #include <fstream> using namespace std; int f[65]; int color[65]; int cnt; int totalLength; bool cmp(int a,int b) { return a>b; } bool DFS(int length,int res,int num)//f从res开始是否可以组成长度length,还剩num根木棍组成 { if(num==1) //剩下一根木棍需要解决,因为之前的都组合成功了,因此剩下的一定组合成功 return true; if(length==0) //成功组成了一根原始木棍,剩余要组合的木棍数为num-1,接下从0开始,继续查看是否可以组成长度totalLentgh return DFS(totalLength,0,num-1); int pre=-1; int i; for(i=res;i<cnt;i++) { if(color[i]==0 && f[i]!=pre && f[i]<=length) //如果用f[i]组成length的木棍没成功,那么后面的f[j],如果f[j]=f[i],也不会成功,直接跳过 { pre=f[i]; color[i]=1; if(DFS(length-f[i],i+1,num))//成功,则退出 break; color[i]=0;//没成功,color[i]仍恢复到原来的状态 if(res==0) //如果res=0,则说明在组合一根新的木棍,如果遇到了未成功,那就说明这个长度不能成功,直接返回错误 return false; } } if(i==cnt) //i枚举到cnt,一直没成功 return false; else return true; } int main() { while((cin >> cnt) && cnt!=0) { int sum=0;//棍子的总长度 for(int i=0;i<cnt;i++) { cin >> f[i]; sum+=f[i]; } sort(f,f+cnt,cmp); //从大到小排列 for(int i=f[0];i<=sum;i++) //棍子的长度要尽可能小,但显然大于等于f[]中的最大值 { if(sum==i) { cout << sum << endl; break; } if(sum%i == 0) { totalLength=i; for(int j=0;j<cnt;j++) color[j]=0; //截下来的小木棍的访问状态 if(DFS(totalLength,0,sum/i)) //从f[0]开始成功组成了长度为totalLength的sum/i根原始木棍 { cout << totalLength << endl; break; } } } } }
附录:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 72642 | Accepted: 15966 |
Description
Input
Output
Sample Input
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0
Sample Output
6 5