poj 1011 sticks

来源:互联网 发布:安卓捏人软件 编辑:程序博客网 时间:2024/06/03 18:02

题意:已知木棍的数量和长度,求这些木棍的最小原始长度。
参考了网上的解题报告,用DFS+剪枝解决,共用到6个剪枝,用时16MS。
代码如下:

#include<iostream>#include<algorithm>using namespace std;#define SIZE 65int stick[SIZE];int visited[SIZE];int n;int dfs(int i,int sum,int curlen,int initlen,int stick[]){    if (sum == n)        return true;    int sample = -1;    for (int j =i; j < n; j++){        if (!visited[j] && sample !=stick[j] ){   //剪枝4:如果一个棍子不行,则与它等长的棍子也不行            visited[j] = 1;            if (curlen+stick[j] <initlen){                if (dfs(j,sum + 1, curlen + stick[j], initlen, stick))                    return true;                else sample =stick[j];            }            if (curlen+stick[j] ==initlen){                if(dfs(0,sum + 1, 0, initlen, stick))                    return true;                else sample =stick[j];            }            visited[j] = 0;            if (curlen == 0)//剪枝5:对于新棍的第一根棍子,搜索完所有棍子后都无法组合,返回上一层                break;            if (stick[j] ==initlen - curlen)//剪枝6:当前棍子长度=剩余所需长度,但后面搜索失败,返回上一层                break;        }    }    return false;}int cmp(const int a,const int b){    return a>b;}int main(){    while (cin >> n){        bool flag = 0;        if (n == 0)            break;        int sumlen = 0;        for (int i = 0; i < n; i++){            cin >> stick[i];            sumlen += stick[i];            visited[i] = 0;        }        sort(stick, stick+n, cmp); //剪枝1:从大到小排列,减少递归次数        int maxlen = stick[0];        for (int initlen = maxlen; initlen <= sumlen/2; initlen++){  //剪枝2:initlen最大为sumlen/2,最小为maxlen            if (sumlen % initlen == 0 && dfs(0, 0, 0, initlen, stick)){//剪枝3:sumlen能被initlen 整除                cout << initlen << endl;                flag = true;                break;            }        }        if (flag ==false)            cout << sumlen << endl;    }    return 0;}
0 0
原创粉丝点击