2014 UESTC Training for Search Algorithm E

来源:互联网 发布:mysql man pages 编辑:程序博客网 时间:2024/05/02 14:15
回溯+剪枝
对于每个被切开的木棍,只有2中状态要么选要么不选,于是想到回溯dfs方法
dfs的三个参数,当前已经使用过的木棍数量,从第几个木棍开始当前查找,当前和
回溯终点就是使用过的木棍数量等于N;
对于每次查找,如果sum+stick[i]<cur可以继续查找
如果刚好相等那么进行标记从头再查找是否可以凑成第二个完整木棍
剪枝:
1.应该从大到小排序,这样可以递归的次数
2.原完整木棒的长度必然是总分开长度的约束,而且必然大于等于切开后的木棍最长的那一块的长度
3.对于排序后长度相同的木块,相同长度的木块前面如果不选,那么相同长度的木棒一定不选
4.对于每一颗欲要组成的新的木棒,如果可利用的最大木块都大于cur,那么不可能形成木块

那么就是 if (sum==0) return false;

#include <map>#include <set>#include <list>#include <cmath>#include<cctype>#include <ctime>#include <deque>#include <stack>#include <queue>#include <cstdio>#include <string>#include <vector>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#define LL long long#define PI 3.1415926535897932626using namespace std;int gcd(int a, int b){return a % b == 0 ? b : gcd(b, a % b);}int sticks[70];int Min,Max;int N;int cur;int vis[70];int cmp(const int &a,const int &b){    return a>b;}void init(){    Max=0;    for (int i=0;i<N;i++)    {        scanf("%d",&sticks[i]);        Max+=sticks[i];    }    sort(sticks,sticks+N,cmp);    Min=sticks[0];}bool dfs(int num,int index,int sum){    if (num==N)return true;    for (int i=index;i<N;i++)    {        if (vis[i]) continue;//如果当前木条用过那么跳过        if (i>=N) break;        if (sum+sticks[i]<cur)//可能可以递归        {            vis[i]=1;            if (dfs(num+1,i+1,sum+sticks[i])) return true;            vis[i]=0;            int j;            for ( j=i;j<N;j++)                if (sticks[j]!=sticks[i]) break;            i=j-1;        }        else if (sum+sticks[i]==cur)        {            vis[i]=1;            if (dfs(num+1,0,0)) return true;//合成一个约数,那么从头开始            vis[i]=0;            return false;        }        if (sum==0) return false;//针对每一颗新组成的完整木棍,如果当前最大值就大于CUR,那么不可能形成    }    return false;}int main(){    while (scanf("%d",&N)==1)    {        memset(sticks,0,sizeof(sticks));        if (N==0) break;        init();        //printf("%d %d\n",Max,Min);        cur=0;       for (int i=N;i>0;i--)       {           if (Max%i==0 && Max/i>=Min)           {               memset(vis,0,sizeof(vis));               cur=Max/i;               //printf("%d\n",cur);               if (dfs(0,0,0)) {printf("%d\n",cur);break;}           }       }    }    return 0;}


0 0
原创粉丝点击