码迷,mamicode.com
首页 > 其他好文 > 详细

poj1011(深搜+剪枝)

时间:2014-05-06 21:16:11      阅读:329      评论:0      收藏:0      [点我收藏+]

标签:csdn   poj   搜索   

题意:给m根木棍,将它们重新拼成n根一样长的木棍,并使得n尽量大(即每个新木棍尽量短)。


解法:经典的搜索题目。从小到大枚举拼成的新木棍长度,每次枚举进行一次深搜。这题关键是如何剪枝。

         1、当枚举的长度不能整除总长度的时候,剪枝;(这个很显然)

         2、先将木棍从长到短排序,枚举时先尝试长的木棍。(先枚举长的可以使得搜索深度不至于过深)

         3、深搜时,不要企图通过换掉一个新木棍的第一根来改变失败的局面(换掉第一根A,那么A也会在以后的新木棍中被使用,但是已经证明了A无法拼成了,所以不必再尝试下去了)

         4、不要企图换掉新木棍的最后一根来改变失败的局面。(同理3)

         5、如果一根木棍试过不行之后,不用再尝试将其换为之后一样长的木棍了。(很显然的剪枝)

   代码:

/****************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>

using namespace std;

#define eps 1e-8
typedef long long LL;

int n;
int num[100];
bool rem[100];
int position;
int ans=0;
int sum;
bool dfs(int finished,int next,int position,int a)
{
    if(finished==sum/ans)
        return true;
    if(position==n)
        return false;
    int before=-1;
    for(int i=position; i<n; i++)
    {
        if(rem[i]||next+num[i]>ans||num[i]==before) continue;
        rem[i]=1;
        before=num[i];
        if(next+num[i]==ans)
        {
            if(dfs(finished+1,0,0,0))
                return true;
            else
            {
                rem[i]=0;
                return false;
            }
        }
        if(dfs(finished,next+num[i],i+1,a+1))
            return true;
        rem[i]=0;
        if(a==0)
            return false;
    }
    return false;
}
int main()
{
    while(scanf("%d",&n)==1&&n)
    {
        sum=0;
        for(int i=0; i<n; i++)
            scanf("%d",num+i),sum+=num[i];
        sort(num,num+n);
        reverse(num,num+n);
        for(ans=1;; ans++)
        {
            if(sum%ans!=0)
                continue;
            memset(rem,0,sizeof rem);
            position=0;
            if(dfs(0,0,0,0))
                break;
        }
        printf("%d\n",ans);
    }
    return 0;
}

poj1011(深搜+剪枝),布布扣,bubuko.com

poj1011(深搜+剪枝)

标签:csdn   poj   搜索   

原文地址:http://blog.csdn.net/xiefubao/article/details/25116787

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!