【动态规划】背包问题

来源:互联网 发布:淘宝改版中国质造 编辑:程序博客网 时间:2024/06/11 17:36

瞎了眼了,这套题全是卖萌卖够了给你一拳。


题目描述追求简洁无极限。


背包问题

【题目描述】

       有一个容量为W的背包,有N种物品,第i种物品的体积为Ti,价值为Vi

       对于每种物品,你可以选择是否将它放入背包,放入背包的物品的总体积不能超过W,在这个前提下你希望放入背包的物品的总价值最大。

 

【输入数据】

       第一行两个数W,N,表示背包的容量和物品的数量。

       之后N行,每行两个数Ti,Vi,表示第i件物品的体积和价值。

 

【输出数据】

       输出一个数,放入背包的物品的最大总价值。

 

【样例】

bag.in

bag.out

9 3

7 14

5 9

4 7

16

 

【数据规模】

测试点编号

N

W

1

10

100

2

10

100

3

1000

10000

4

1000

10000

5

50

10000000

6

70

10000000

7

100

10000000

8

120

10000000

9

150

100000000

10

200

100000000


尼玛谁看到这么简单的题还去想复杂方法?结果超时6组。。

题目范围太坑爹,加之没有说清楚。。其实题上漏掉了一个条件,就是总价值不超过100000,可以添到题设中去。


所以我们可以分两种情况,普通01背包最大限度是N*W=1000*10000。超出这个范围我们就换一种思路。

f[i][j] 表示 前i种物品 价值为j ,最少体积是多少次。同样可以就地滚动。


加注释的是改进了的地方,一开始还是超时,修改了一个地方,对如果算出来的新体积比W大了,就不更新(其实这只是优化了一点小小的系数,因为如果不加这个优化,状态转移是两个时钟周期,加上了可以优化到接近一个。= =、这是多么小一个优化呀。实际执行效果很好。)

#include <cstdio>#include <string>#include <cstring>#define MAX(a,b) ((a)>(b)?(a):(b))#define MIN(a,b) ((a)<(b)?(a):(b))long getint(){long rs=0;bool sgn=1;char tmp;do tmp = getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp == '-'){tmp=getchar();sgn=0;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;}//long w[1010];//long v[1010];long f[1000010];int main(){freopen("bag.in","r",stdin);freopen("bag.out","w",stdout);long W = getint();long n = getint();//for (long i=1;i<n+1;i++)//{//w[i] = getint();//v[i] = getint();//}if (W <= 10000){for (long i=1;i<n+1;i++){long w = getint();long v = getint();for (long j=W;j>=w;j--){f[j] = MAX(f[j],f[j-w]+v);}}long ans = 0;for (long i=0;i<W+1;i++)ans = MAX(ans,f[i]);printf("%ld",ans);}else{memset(f,0x7f,sizeof f);f[0] = 0;for (long i=1;i<n+1;i++){long w = getint();long v = getint();for (long j=1000000;j>=v;j--){//if (f[j-v]+w <= W)//f[j] = MIN(f[j],f[j-v]+w);}}for (long j=1000000;j>=0;j--)if (f[j] <= W){printf("%ld",j);break;}}return 0;}

另附一个开散列优化的版本1(事实证明,用这种方法使空间压力更大了,几乎是难以承受)主要弊端在于

it1 = hash[now].find(it2->first);if (it1 == hash[now].end())hash[now].insert(*it2);elseit1 -> second = MAX(it1->second,it2->second);
因为实际上我是用的01滚动的原理,来搞的,但是其实只有f数组需要01滚动(为了解决后效性问题),而hash表(我也不知道为什么我要)是不需要滚动的(因为01背包,每一种体积都会保留到下一个阶段)

#include <string>#include <cstring>#include <cstdio>#define MAX(a,b) ((a)>(b)?(a):(b))#include <map>using std::map;using std::iterator;using std::make_pair;long w[1010];long v[1010];long f[10000010];long getint(){long rs=0;bool sgn=1;char tmp;do tmp = getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp == '-'){tmp=getchar();sgn=0;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;}map<long,long> hash[2];map<long,long>::iterator it1;int main(){freopen("bag.in","r",stdin);freopen("bag.out","w",stdout);long W = getint();long n = getint();for (long i=1;i<n+1;i++){w[i] = getint();v[i] = getint();}long pre = 0;long now = 1;hash[now][0] = 0;for (long i=1;i<n+1;i++){pre ^= 1;now ^= 1;hash[now].clear();for (map<long,long>::iterator it2=hash[pre].begin();it2!=hash[pre].end();it2++){if (it2->first+w[i] <= W){it1 = hash[now].find(it2->first+w[i]);if (it1 == hash[now].end())hash[now].insert(make_pair(it2->first+w[i],it2->second+v[i]));elseit1 -> second = MAX(it1->second,it2->second+v[i]);}it1 = hash[now].find(it2->first);if (it1 == hash[now].end())hash[now].insert(*it2);elseit1 -> second = MAX(it1->second,it2->second);}}long ans = 0;for (map<long,long>::iterator it2=hash[now].begin();it2!=hash[now].end();it2++){ans = MAX(ans,it2->second);}printf("%ld",ans);return 0;}


基于以上问题,做了优化,实际效果也不理想

#include <string>#include <cstring>#include <cstdio>#define MAX(a,b) ((a)>(b)?(a):(b))long w[1010];long v[1010];long weight[2][5000000];long f[2][5000000];long ths = 0;long pre = 1;const long hmod = 200000;long getint(){long rs=0;bool sgn=1;char tmp;do tmp = getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp == '-'){tmp=getchar();sgn=0;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;}long cnt[2];struct node{long s;long id;node* nxt;};node* head[hmod+10];node memory[5000000];long get_id(long s){long h = s % hmod;for (node* u=head[h];u;u=u->nxt)if (u->s == s) return u->id;cnt[ths] ++;f[ths][cnt[ths]] = 0;node* nn = &memory[cnt[ths]];nn -> nxt = head[h];nn -> id = cnt[ths];nn -> s = s;head[h] = nn;weight[ths][cnt[ths]] = s;return cnt[ths];}void clear(){cnt[ths] = 0;memset(head,0,sizeof head);}void updata(long &a,long b){if (b > a)a = b;}int main(){freopen("bag.in","r",stdin);freopen("bag.out","w",stdout);long W = getint();long n = getint();for (long i=1;i<n+1;i++){w[i] = getint();v[i] = getint();}f[ths][get_id(0)] = 0;for (long i=1;i<n+1;i++){pre ^= 1;ths ^= 1;clear();for (long j=1;j<cnt[pre]+1;j++){if (weight[pre][j]+w[i] <= W)updata(f[ths][get_id(weight[pre][j]+w[i])],f[pre][j]+v[i]);updata(f[ths][get_id(weight[pre][j])],f[pre][j]);}}long ans = 0;for (long j=1;j<cnt[ths]+1;j++){ans = MAX(ans,f[ths][j]);}printf("%ld",ans);return 0;}


原创粉丝点击