3307 背包,次优解

来源:互联网 发布:龙魂时刻数据解析失败 编辑:程序博客网 时间:2024/06/05 14:22

a

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

有一个奇怪的超市,超市中有m种商品,每个商品都有一个都价格pi,超市的特殊在于:如果顾客买第i种商品,就会赠送ci个欢乐豆,一种商品对一个顾客只会赠送一次。现在有两个好朋友来超市买东西,他们都带了n元钱,如果最终两个人得到的欢乐豆不一样,他们的欢乐豆的和的最大值是多少?

输入

 首先输入一个正整数T (T<10),测试数据有T组。
对于每组测试数据的第一行有两个整数n,m ( 1 <= n,m <= 1000)。之后有m行,每行两个数字p c,代表第i种商品的价格是p,赠送的欢乐豆的数量c(1 <= p,c <= 1000).

输出

 输出一个整数,表示两个人获得的欢乐豆的和的最大值。

示例输入

110 32 33 55 8

示例输出

29

提示

 第一个人可以买第1,2,3种商品,得到的欢乐豆是16,第二个人也可以买1,2,3这三种商品,但是不能和第一个人得到的欢乐豆一样,所以最多可以得到13个欢乐豆。

来源

windream

示例程序

 
#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#define INF 0x3f3f3f3fusing namespace std;int c[10000],p[10000];int dp1[10000],dp2[10000];int main(){int n,m,t;while(~scanf("%d",&t)){while(t--){scanf("%d%d",&n,&m);memset(dp1,0,sizeof(dp1));     memset(dp2,-INF,sizeof(dp2));  //将dp2[]初始化为-INF就可以将所有情况都罗列出来, 即dp[j]为非负数时对应的是装满时的最大价值,如果为负数表示未装满for(int i=1;i<=m;i++)            //此时dp2[n]不一定为最大值了{scanf("%d%d",&p[i],&c[i]);}for(int i=1;i<=m;i++)for(int j=n;j>=p[i];j--){dp1[j]=max(dp1[j],dp1[j-p[i]]+c[i]);}dp2[0]=0;int Max=0;for(int i=1;i<=m;i++)for(int j=n;j>=p[i];j--){dp2[j]=max(dp2[j],dp2[j-p[i]]+c[i]);if(Max<dp1[n]&&dp1[n]>dp2[j]&&Max<dp2[j]){Max=dp2[j];               //记录了装满时(体积恰好为j)时的价值。}}printf("%d\n",dp1[n]+Max);}}}

0 0
原创粉丝点击