hdu1455 poj1011 hoj1049 Sticks 深搜+剪枝

由于明天要给大一的同学讲搜索,所以临时放下了线段树,刷几个搜索题,结果这个题就从早上卡我到现在。

题意就是将一些值分成若干份求和使得他们的和相等,求出最小的能满足条件的和

这道题的关键之处在于剪枝:

1、这个和肯定整除所有数的总和,且这个和最小就是这些数中的最大值,所以枚举和的时候可以先剪枝

2、搜的过程中,如果当前的和加上剩下所有的和小于目标和,则直接返回0

3、当前和与目标和的差小于所有数的最小值,则直接返回0

4、在当前情况下,不对相同的值进行搜索,因为这显然是没有意义的

5、当前情况下,要搜索的数需要满足,加上当前和依然小于等于目标和

6、如果当前情况下,能够找到一个数,使得他加上当前和恰好等于目标和,那么如果这么搜下去不行的话,直接跳出当前循环,理由:

假设当前和比目标和小5,剩下的书中有5,2,2,1  那么可以有两种情况,要么直接拿5,要么拿2,2,1,但是,因为2,2,1相当于是5,但是他们比5更灵活,即在之后的情况下,2,2,1显然比5更有利,因为2,2,1既能合在一起当5用,又能拆开来用,也就是说,如果我现在拿了5找不到正确结果,我拿2,2,1更加不可能,所以,这种情况下,如果找不通,就没必要往下找了    (我被这步剪枝卡了很久,没有这步,在某些数据下会很慢,尤其是1很多的时候)

7、这些数是按从大到小排序的,这样能更加快的到达目标和

8、如果已经找到答案,直接退出深搜

9、每次从0开始搜的时候可以固定第一个值

-------------------------这样就能0.00s过了,其中1,4,6,7是主要的剪枝-----------------------

另外不可以一组一组深搜,即先找到一组和,再找下一组,我刚开始有个误区,以为组合的时候一定是字典序越大越好,即,我之前认为同样是9   5,3,1要优于5,2,2

但其实不能这样,这样虽然在不少情况下都是对的,还是能找到错误数据,poj的discuss里有数据,在此附上链接 http://poj.org/showmessage?message_id=172549

以下是AC代码:


#include 
#include 
#include 
#include 
using namespace std;
int a[100];
bool vis[100];
int sum[100];
int n;
bool findans;
int cmp(const int &a,const int &b)
{
    return a>b;
}
bool dfs(int k,int x,int y)
{
    if(findans) return 1; //剪枝8
    if(x==y)
    {
    	int m = -1;
        for(int i=0; isum[n-1]-(k)?sum[k-1]:0) return 0; //剪枝2
    if(x-y


你可能感兴趣的:(ACM算法)