[DFS+剪枝]POJ 1011/HDOJ 1455/HOJ 1049 Sticks

来源:互联网 发布:淘宝短信催付款话术 编辑:程序博客网 时间:2024/06/08 18:34

传送门:

POJ:http://poj.org/problem?id=1011

HDOJ:http://acm.hdu.edu.cn/showproblem.php?pid=1455

HOJ:http://acm.hit.edu.cn/hoj/problem/view?id=1049

Sticks

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5206    Accepted Submission(s): 1456


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


解题报告:

这是一道经典的搜索剪枝题。

解法:

在刚开始搜索组成一支新的长为 L 的木棍时,我们总是以当前最长的,未被使用的,木棍开始,如果搜索不成功,那么以比它短的开始, 这时也一定不能取得全局的成功。因为每一支题目给出的木棍都要被用到。代码如下:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;bool visited[65];//标记是否访问过int snum; //分火柴棍int sum;//总分火柴棍长度之和int sticks[65];//储存分火柴棍int l;//合起来每根火柴棍长度int num;//合起来有多少根火柴棍bool dfs(int s,int slen,int pos){//s当前已经分配好的火柴棍,slen当前总长度,pos当前第几个火柴棍    if(s==num)        return true;    bool sign =(slen==0?true:false);    for(int i=pos+1;i<snum;i++){        if(visited[i]==true)    //该根火柴访问过            continue;        if(slen+sticks[i]==l){            visited[i]=true;            if(dfs(s+1,0,-1))                return true;            else{                visited[i]=false;                return false;            }        }        else if(slen+sticks[i]<l){            visited[i]=true;            if(dfs(s,slen+sticks[i],i)) //没达到继续加下一根                return true;            else{                visited[i]=false;                if(sign)                    return false;            }        }    }    return false;}bool cmp(int a,int b){    return a>b;}int main(){    while(scanf("%d",&snum)==1&&snum){        sum=0;        for(int i=0;i<snum;i++){            scanf("%d",&sticks[i]);            sum+=sticks[i];        }        sort(sticks,sticks+snum,cmp);        for(l=sticks[0];l<=sum;l++){            if(sum%l==0){                num=sum/l;                memset(visited,false,sizeof(visited));                if(dfs(1,0,-1)){//第一次找到的肯定是最大的                    printf("%d\n",l);                    break;                }            }            else                continue;        }    }    return 0;}


0 0
原创粉丝点击