POJ 1011 木棒

木棒
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 138745 Accepted: 32693

Description
乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。

Input
输入包含多组数据,每组数据包括两行。第一行是一个不超过64的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。

Output
为每组数据,分别输出原始木棒的可能最小长度,每组数据占一行。

Sample Input

9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0

Sample Output

6
5


第二次做这题了 上学期做了一次 再做还是不会..翻回以前代码才过了
刚开始穷举每一种木棒组合 然后dfs验证这个长度
坑爹啊..枚举了2^n种情况
原本的木棒可能长度len只在 max(a1,a2,...,an)<=len<=a1+a2+...+an<=50*n范围内
完全可以穷举长度
加上各种剪枝 终于过了

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair
#define INF 1000000007
#define pll pair
#define pid pair

#define sci(a) scanf("%d",&a)
#define scll(a) scanf("%lld",&a)
#define scd(a) scanf("%lf",&a)
#define scs(a) scanf("%s",a)
#define pri(a) printf("%d\n",a)
#define prll(a) printf("%lld\n",a)
#define prd4(a) printf("%.4lf\n",a)
#define prd(a) printf("%lf\n",a)
#define prs(a) printf("%s\n",a)
//#define CHECK_TIME

int len[65],n;
bool used[65];

bool dfs(int uses,int nowlen,int LEN){
/*uses用了多少根木棒 
nowlen当前组合出来的长度 
LEN要恢复成的长度*/
    if(uses==n)
        return nowlen==LEN;
    if(nowlen==LEN){//如果长度已经组合出LEN 将nowlen设为0 继续找
        int st=0;
        while(used[st])//每一根木棒都要被用掉 所以直接选择一根没用过的 
            ++st;
        used[st]=true;
        bool res=dfs(uses+1,len[st],LEN);//用st木棒
        used[st]=false;
        return res;
    }
    for(int i=1;iif(used[i])//用过了
            continue;
/*如果len[i]==len[i-1] 选择了len[i-1]时不选len[i]的情况 和 现在的情况(len[i]选了 len[i-1]不选)等价 所以没必要再重复检查*/
        if(len[i]==len[i-1]&&used[i-1]==false)
            continue;
        if(len[i]+nowlen<=LEN){//组合起来长度不超过LEN
            used[i]=true;
            if(dfs(uses+1,nowlen+len[i],LEN))
                return true;
            used[i]=false;
        }
    }
    return false;
}

int work(){
    int MAX=0;
    sort(len,len+n,greater<int>());
    fill(used,used+n,false);
    used[0]=true;//第0根木棒一定要被用掉 直接用了它
    for(int i=0;i//计算总长度
        MAX+=len[i];
    for(int i=len[0];i<=MAX;++i)//木棒长度在len[0]到MAX之间
        if(MAX%i==0&&dfs(1,len[0],i))//如果i不能被MAX整除 肯定不能恢复
            return i;
}

int main()
{
    //freopen("/home/lu/文档/r.txt","r",stdin);
    //freopen("/home/lu/文档/w.txt","w",stdout);
#ifdef CHECK_TIME
    time_t now=clock();
#endif

    while(sci(n),n){
        for(int i=0;i#ifdef CHECK_TIME
    cout<<"cost time:"
       <<(double)(clock()-now)/CLOCKS_PER_SEC*1000
      <<"ms"<#endif
    return 0;
}

你可能感兴趣的:(POJ,搜索,剪枝,HDU,poj,剪枝,搜索)