【DFS+多次剪枝】HDU1455Sticks【POJ少林神棍】

来源:互联网 发布:js trigger click 编辑:程序博客网 时间:2024/04/27 19:40

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1455

Problem 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. 
 

Input
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.
 

Output
The output file contains the smallest possible length of original sticks, one per line. 
 

Sample Input
95 2 1 5 2 1 5 2 141 2 3 40
 

Sample Output
65

这是个很好的题目,综合力很强!!!


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;bool cmp(int a,int b){return a>b;}int L,n,sum;int a[1010];int vis[1010];//int ss,s;int dfs(int s,int N,int M)        //  N:剩余木棍总数;M:拼成一根长度为L的木棍还需M长度;s为开始的位置(剪枝){    if(N==0&&M==0) return 1;        //  表示刚好可以拼成长度为M的小木棍;    if(M==0) M=L,s=0;           //  拼完一根,M重新赋值为L,拼下一根;    //int ss=0;    //if(M!=L) ss=s+1;    for(int i=s;i<n;i++){        if(!vis[i]&&a[i]<=M){       //  没有用过的,且长度小于M;            if(i&&!vis[i-1]&&a[i]==a[i-1]) continue;  //  剪枝,i-1,i的长度一样,如果i-1没有被使用,那么i也不可能被使用;            vis[i]=1;            //s=i;            if(dfs(i+1,N-1,M-a[i])) return 1;            else{                vis[i]=0;                if(M==L) return 0;      //  第一根就不适用(剪枝);                if(M==a[i]) return 0;   //  剪枝;如果a[i]刚好可以凑成一根完整的木棍,但是没有用,那么无法所有的木棍长度都为L;            }        }    }    return 0;}int main(){    cin.sync_with_stdio(false);    while(cin>>n&&n){        sum=0;        for(int i=0;i<n;i++){            cin>>a[i];            sum+=a[i];        }        sort(a,a+n,cmp);        for(L=a[0];L<=sum/2;L++){            if(sum%L) continue;         //  如果无法整除,不用考虑;            memset(vis,0,sizeof(vis));            if(dfs(0,n,L)){                cout<<L<<endl;                break;            }        }        if(L>sum/2) cout<<sum<<endl;        //  只能合成一根木棍;    }    return 0;}


0 0