zoj 4777 Watashi's BG DFS解决01背包

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4777

本来想的算法是如果V<=100000就直接进行01背包时间复杂度为O(30*100000),如果大于100000大于部分贪心选择,剩余部分在进行01背包,可是中间会出现很多问题,大于部分的的处理不好弄,如果100000加上处理后的剩余部分会出现数组越界,再说有的数据也不会过,这只是一种yy的方法,不对。

后来据说是爆搜解决01背包想了想时间复杂度能够达到(10^9自己不敢写,竟没有想到剪枝弄好了能够过,于是就写了起来,这里首先从大到小排序,这样大的在前边保证先装大的,背包容量就会变小再加剪枝就能过了。

View Code
#include <cstdio>

#include <algorithm>

#define maxn 44

using namespace std;



int w[maxn],n,b[maxn];

int V,ans;



int cmp(int a,int b)

{

    return a > b;

}

void dfs(int sum,int num)

{

    if (sum > V) return ;

    if (num >= n)

    {

        ans = max(ans,sum);

        return ;

    }

    int tmp = sum;

    if (num > 0)

    tmp += (b[n - 1] - b[num - 1]);//如果当前加上剩余没有选的物品的总和小于原来最大的

    if (tmp < ans) return ;

    dfs(sum + w[num],num + 1);

    dfs(sum,num + 1);

}

int main()

{

    int i,ni;

    while (~scanf("%d%d",&ni,&V))

    {

        for (int i = 0; i < ni; ++i) scanf("%d",&w[i]);



        int s = 0; n = 0;

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

        {

            b[i] = 0;

            if (w[i] <= V)//将大于总容量的物品剪掉

            {

                w[n++] = w[i];

                s += w[i];

            }

        }

        if (s <= V)//总和小于总容量

        {

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

            continue;

        }

        sort(w,w + n,cmp);

        //b记录前i项和

        b[0] = w[0];

        for (i = 1; i < n; ++i) b[i] = b[i - 1] + w[i];



        ans = 0;

        dfs(0,0);

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

    }

    return 0;

}

你可能感兴趣的:(DFS)