搜索剪枝回溯经典题目 pku 1011 sticks

来源:互联网 发布:办公室软件免费下载 编辑:程序博客网 时间:2024/04/29 05:54

题目:

http://acm.pku.edu.cn/JudgeOnline/problem?id=1011

 

 

 

#include <stdio.h>#include <algorithm>#define max 65int sticks[max];bool used[max];int M;int cmp(const void *e1,const void *e2){return (*(int *)e1) - (*(int *)e2) > 0 ? -1 : 1;}bool f(int k,int left,int L,int N){//能否将k根木板拼成N根L长的木棒加上一根left长的木棒if(k == 0 && left == 0 && N == 0)//如果在k=0的时候left=N=0,则说明可以完成这种组合return true;if(left == 0)//已经拼好一根木板的时候//那么剩下的木棒数量就减一,同时新模板的长度为Lreturn f(k,L,L,N - 1);//t = max{stick <= left && used == false}for(int i = 0;i < M;i++)if(sticks[i] <= left && !used[i]){used[i] = true;if(f(k - 1,left - sticks[i],L,N))return true;//回到当前状态used[i] = false;//这个剪枝条件想了好久~~~最后还是看书了。。。—_-`//这个回溯 好牛逼!!!//一.当前状态为死节点//二.木棒长度为剩余left段的第一个位置或者最后一个位置//可想而知是找不到替换木棒的  总是会多出这么一段left。。。if(sticks[i] == left || left == L)break;}//剪枝条件,找不到t,当前状态不合法.return false;}int main(){FILE *fp = fopen("data.txt","r");while(scanf("%d",&M)/*fscanf(fp,"%d",&M)*/,M){int i,stick,len,sum;sum = 0;for(i = 0;i < M;i++){scanf("%d",&stick);//fscanf(fp,"%d",&stick);sticks[i] = stick;sum += stick;}qsort(sticks,M,sizeof(sticks[0]),cmp);len = sticks[0];memset(used,false,M);for(i = len;i <= sum;i++){if(sum % i)continue;if(f(M,0,i,sum / i)){printf("%d/n",i);break;}}}return 0;}