[POJ 1011] Sticks DFS神剪枝

来源:互联网 发布:软件开发服务 编辑:程序博客网 时间:2024/06/03 00:04

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

题意:给你很多的碎木块,要你拼成一些等长的木棍,问这些木棍的最短长度是多少

一开始我用的是枚举要拼成多少木棍,搜索的时候把每根碎木块放到不同的木棍上,然后毫无人性的TLE了,这种索搜的局限主要就是不能提前知道能否拼出所枚举的长度,所以少了一个重要的剪枝。

思路:想加上上面的剪枝就必须依次填满每根木棍,出现不能填出所枚举的长度的时候就剪枝。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int n;int mapn[105];bool vis[105];bool cmp(int a, int b){    return a > b;}//从第pos根碎木快开始,已经累加的长度,枚举的长度,填第几根木棍,总共要填几根bool Dfs(int pos, int sum, int lens, int st, int ed){    if(st == ed) //填完所有木棍        return true;    if(sum == lens) //填完当前木棍        return Dfs(0, 0, lens, st+1, ed);  //填下一根    for(int i = pos, pre = 0; i < n; i++){        if(vis[i] || sum + mapn[i] > lens || pre == mapn[i]) //剪枝            continue;        pre = mapn[i]; //保存前一个,方便剪枝        vis[i] = true; //标记被用过了        if(Dfs(i+1, sum+mapn[i], lens, st, ed))            return true;        vis[i] = false;        if(pos == 0)         //最重要的剪枝,表示第i根木棍和剩下的所有木棍都不能凑出一根长度为lens的木棍            return false;    }    return false;}int main(){    while(cin>>n && n){        int sum = 0;        for(int i = 0; i < n; i++){            cin>>mapn[i];            sum += mapn[i];        }        sort(mapn, mapn+n, cmp);        for(int i = n; i > 0; i--){            memset(vis, false, sizeof(vis));            if(sum % i == 0 && Dfs(0, 0, sum/i, 0, i)){                cout<<sum/i<<endl;                break;            }        }    }    return 0;}
0 0