HDU 1455(Sticks) POJ 1011(Sticks)

/*DFS好题
Date: 2012/10/14
题目链接地址:http://poj.org/problem?id=1011
                    http://acm.hdu.edu.cn/showproblem.php?pid=1455
思路:首先可以确定的是,木棍初始值的长度肯定是所有木棍段之和(假设为sum)的约数,木棍初始值的最小值
      为给定木棍段的最大值(假设为max),木棍初始值的最大值为所有木棍段之和。所以从max到sum之间依次
   判断是sum约数的长度是否满足题目要求即可
   先给木棍段从大到小排序,这对以后的剪枝有帮助
   剪枝1:在刚开始组成一个初始木棍的时候,如果某木棍段的长度小于初始木棍的长度且不满足的话,则返回
   剪枝2:如果一个木棍段的长度和木棍初始值相等,且不满足的话,则返回
   剪枝3:如果木棍段的值不满足的话,那么和当前木棍段相等的木棍段也不满足
*/

#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 65
int n,sum,arr[maxn];
bool flag,visited[maxn];
bool cmp(int a,int b)
{
    return a > b;
}
void dfs(int k,int i,int s,int num)//k表示初始值,i表示当前值的下标,s表示当前木棍长度的和,num表示已用的木棍段的数量
{
    if(num == n && s == k)
    {
        flag = 1;
        return;
    }
    if(flag)   return;
    s = s%k,visited[i] = true;
    for(int j = 1; j <= n; j++)
    {
        if(!visited[j] && s+arr[j] <= k)
        {
            dfs(k,j,s+arr[j],num+1);
            if(s == 0 && arr[j] < k)  break;//刚开始如果当前值小于初始值且不满足的话,那么这个初始值是不合法的
            if(arr[j] == k)   break; //当前值等于初始值不行的话,那这个初始值就是不合法的
            while(arr[j] == arr[j+1]) j++; //当前值不行,那与当前值相等的也不满足
        }
    }
    visited[i] = false;
}
int main()
{
    //freopen("1010.txt","r",stdin);
    while(scanf("%d",&n) && n)
    {
        int i;
        sum = flag = 0;
        for(i = 1; i <= n; i++)
        {
            scanf("%d",&arr[i]);
            sum += arr[i];
        }
        sort(arr+1,arr+n+1,cmp);
        for(i = arr[1]; i <= sum; i++)
        {
            if(i == sum)
            {
                printf("%d\n",sum);
                break;
            }
            if(sum%i == 0)
                dfs(i,1,arr[1],1);
            if(flag)
            {
                printf("%d\n",i);
                break;
            }
        }
    }
    return 0;
}

 

posted @ 2012-10-14 22:53  sorryhao  阅读(164)  评论(0)    收藏  举报