POJ1011———Sticks

/*dfs,剪枝是关键。╮(╯▽╰)╭本来是想一根棍子

一个棍子的填充,遇到棍子不合适的就回溯。但是实验

证明这绝对是剪错方向的!正确的解法是。。。先寻找

第一根棍子合不合适,如果不合适就没有必要找下去了,

这是关键点。这题堪称剪枝之最啊~~~~~

*/



#include<cstdio>

#include<cstring>

#include<algorithm>

#include<iostream>

#include<queue>

using namespace std;

#define M 100

typedef long long LL;

int N,a[M],mark,vis[M],m;

bool dfs(int num,int re,int dul) //当dul等于0,就是重新找棍子的开始

{

    if(num==1) return true;

    int p;

    for(int i=0; i<N; ++i)

    {

        if(!vis[i])

        {

            if((p=re+a[i])<mark) //拼凑棍子

            {

                vis[i]=1;

                if(dfs(num,p,i+1)) return true;

                vis[i]=0;

                if(dul==0) break; //如果这个棍子找不到,就没有必要找下去了

            }

            else if(p==mark) //拼凑成功

            {

                vis[i]=1;

                if(dfs(num-1,0,0)) return true;

                vis[i]=0;

                break; //如果找不到这根新的棍子就没有必要继续下去了。

            }

        }

    }

    return false;

}

bool cmp(int m,int n)

{

    return m>n;

}

int main()

{

//freopen("abc.txt","r",stdin);

    while(~scanf("%d",&N)&&N)

    {

        int sum=0;

        for(int i=0; i<N; ++i)

        {

            scanf("%d",&a[i]);

            sum+=a[i];

        }

        sort(a,a+N,cmp);

        int mmd=a[0];

        while(1)

        {

            while(sum%mmd!=0) //寻找可以被sum整除的数

                mmd++;

            memset(vis,0,sizeof(vis));

            mark=mmd;

            if(dfs(sum/mmd,0,0)) break;

            mmd++;

        }

        printf("%d\n",mmd);

    }

}

 

你可能感兴趣的:(poj)