您的位置:首页 > 其它

poj1011

2014-07-29 09:56 134 查看
这道题提交20多次才通过。主要原因是没有每次将flag标志重置为false。
思想:木棒长度肯定介于最大的木棒长度和木棒总长度之间,且是木棒总长度的约数(因素)。
第一步:对输入的从大到小排序,同时求出木棒总长度。
第二走:从最长木棒到木棒总长度之间一次循环,显然数组的一个根就是最长木棒。
第三步:深度搜索。记录当前拼凑木棒的长度,当前数组访问下表,当前深搜深度。
(1)如果当前拼凑木棒长度为0,那么取出没有访问过的最长木棒,继续深搜。
(2)如果当前拼凑木棒长度==需要拼凑出来的木棒长度,本次拼凑完成。如果深度为总木棒数,表示深搜完成,退出。
否则,继续深搜。
(3)如果当前拼凑木棒长度小于等于需要拼凑出来的木棒长度,则开始查找,查找未访问的,且待用长度与目前拼凑木棒长度小于等于拼凑出来的木棒长度。
  需要剪枝,如果上一个拼凑不成功,且这一个和上一个长度一致,则这一个也和上次一样不会成功。
  否则,继续深搜。
  拼凑不成功,必须回溯,即将未拼凑成功的重置未访问标志。
深搜完成,可以提前退出。找到木棒长度,立即终止循环。
肯定会有答案出现,所有搜索不成功时,木棒总长度即为答案。
#include<iostream>#include<algorithm>#define SIZE 65using namespace std;int n;//木棒数目int a[SIZE];//木棒长度数组int visit[SIZE];//访问标志数组int len;//当前测试的长度int flag = 0;//完成标志int compare(int a, int b){if( a>b)return 1;return 0;}//dep表示已经使用过的小棒数目,curlen表示当前需要拼凑的小棒长度,pos表示当前数组下标void dfs(int dep,int curlen,int pos ){//  cout<<dep<<" "<<curlen<<" "<<pos<<endl;if(flag )return ;if(curlen == 0){int k= 0;while(visit[k])k++;visit[k] = 1;dfs(dep + 1, a[k], k + 1);//visit[k] = 0; //如果没有成功,需要回溯return ; //如果未成功,直接退出}if(curlen == len){//拼凑完成if(dep == n) flag = 1;else dfs(dep, 0, 0);return ;    // 如果未成功,直接退出}for(int i = pos; i < n; i ++)//当前curlen未拼凑满时if(!visit[i] && curlen + a[i] <= len)//可能拼凑成功{if(!visit[i-1] && a[i] == a[i-1])//上一个未被访问,上一个和这一个数值一样,则这一个也不会被访问continue;visit[i] = 1;//否则,可以拼凑dfs(dep + 1, curlen + a[i], i + 1);visit[i] = 0;//如果未成功,则回溯}}int main(void){while(cin>>n && n>0){int sum = 0;//记录木棒总长度//接收输入flag = 0;for(int i=0;i<n;i++){cin>>a[i];sum += a[i];}sort(a,a+n,compare);for(len=a[0];len<sum;len++){if(sum % len == 0){memset(visit,0,sizeof(visit));//清空访问数组dfs(0, 0, 0);if(flag) break;}}cout<<len<<endl;}//system("pause");return 0;}       
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: