Nyoj289苹果(01背包)
时间限制:3000 ms | 内存限制:65535 KB
难度:3
描述
ctest有n个苹果,要将它放入容量为v的背包。给出第i个苹果的大小和价钱,求出能放入背包的苹果的总价钱最大值。
输入
有多组测试数据,每组测试数据第一行为2个正整数,分别代表苹果的个数n和背包的容量v,n、v同时为0时结束测试,此时不输出。接下来的n行,每行2个正整数,用空格隔开,分别代表苹果的大小c和价钱w。所有输入数字的范围大于等于0,小于等于1000。
输出
对每组测试数据输出一个整数,代表能放入背包的苹果的总价值。
样例输入
3 3
1 1
2 1
3 1
0 0
样例输出
2
#include<stdio.h>
#include<string.h>
#define N 1001
int dp[N];
int max(int a,int b)
{
if(a>b)
return a;
else
return b;
}
int main()
{
int n,v,i,j,c,w;
while(scanf("%d %d",&n,&v))
{
if(n==0&&v==0)
break;
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
{
scanf("%d %d",&c,&w);
for(j=v;j>=c;j--)
dp[j]=max(dp[j],dp[j-c]+w);
}
printf("%d\n",dp[v]);
}
return 0;
}
又见01背包
时间限制:1000 ms | 内存限制:65535 KB
难度:3
描述
有n个重量和价值分别为wi 和 vi 的 物品,从这些物品中选择总重量不超过 W
的物品,求所有挑选方案中物品价值总和的最大值。
1 <= n <=100
1 <= wi <= 10^7
1 <= vi <= 100
1 <= W <= 10^9
输入
多组测试数据。
每组测试数据第一行输入,n
和 W ,接下来有n行,每行输入两个数,代表第i个物品的wi 和 vi。
输出
满足题意的最大价值,每组测试数据占一行。
样例输入
4 5
2 3
1 2
3 4
2 2
样例输出
7
这道题其实和一般的01背包没有什么区别,只是这道题目按照正常的思维去做不行了,因为容量太大,开个10^9的数组开不了,所以这时候就需要换种思维,这个题刚开始没理解,后来在网上在题解,发现都说是互换重量和价值,但是一直没理解什么意思,后来,仔细想了想那个最最基础的01背包是怎么推出来的才想通了, 也不能说是互换价值和重量,那样其实并不能加深理解,做完这个题之后,发现又对背包理解深了一点,写个博客,留下纪念
这道题很容易发现其实重量很大,达到10^9,但是价值很小啊,现在就来推一下这个所谓的“互换”是怎么来的 (其实我觉得还不如从最原始的来,不叫做“互换”好理解点), 最原始的那个式子
dp[i][j]表示当取 i 个, 重量为 j 的时候背包的最大价值,状态转移方程就是 dp[i][j] = max(dp[i - 1][j], dp[i-1][j - weight[i]] + value[i]), 这个式子的意思想必大家都明白吧,前面的那个意思是不取当前这个,后面的这个是取上当前这个物品, 后来再经空间优化之后变成了dp[j] = max(dp[j], dp[j - weight[i]] + value[i]), 仔细观察会发现二维数组时,那两种状态都是i - 1,所以就可以去掉,但是得注意,循环遍历的时候要逆序,正序的话就成完全背包了, 忘了说这个dp[j]表示什么了, dp[j]就是 当取到重量为j 的时候的最大价值。弄明白了这些。这时候就可以来看这个题了, 题目要求和普通的01背包一样,求能装的最大价值,普通方法就是直接找最大价值,现在要换种思维,找最小的重量, 因为同样价值,重量越小,那么最后能装的价值就可能越大,所以这个dp[i][j]就表示 当 取 i 个, 价值为j 的时候的最小重量,状态转移方程为 dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - value[i]] + weight[i]), 和那个最初推的一样,不再罗嗦,空间优化之后状态转移方程为dp[j] = min(dp[j], dp[j - value[i]] + weight[i]), 同样的意思,dp[j]表示 价值为j 的时候的最小重量,到最后只要从最大价值往下遍历这个dp数组,只要找到dp[j] <= 背包重量的时候就直接输出 j , 这时候j就是最大的。
#include<stdio.h>
#include<string.h>
#define Min(a,b) a<b?a:b
#define N 10003
int dp[N];
int weight[102];
int value[102];
int main()
{
int n,w;
while(~scanf("%d %d",&n,&w))
{
int sum=0;
for(int i=0;i<n;i++)
{
scanf("%d%d",&weight[i],&value[i]);
sum+=value[i];
}
memset(dp,111,sizeof(dp));
dp[0]=0;
for(int i=0;i<n;i++)
{
for(int j=sum;j>=value[i];j--)
dp[j]=Min(dp[j],dp[j-value[i]]+weight[i]);
}
for(int i=sum;i>=0;i--)
if(dp[i]<=w)
{
printf("%d\n",i);
break;
}
}
return 0;
}
Nyoj311完全背包
时间限制:3000 ms | 内存限制:65535 KB
难度:4
描述
直接说题意,完全背包定义有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的体积是c,价值是w。求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。本题要求是背包恰好装满背包时,求出最大价值总和是多少。如果不能恰好装满背包,输出NO
输入
第一行: N 表示有多少组测试数据(N<7)。
接下来每组测试数据的第一行有两个整数M,V。 M表示物品种类的数目,V表示背包的总容量。(0<M<=2000,0<V<=50000)
接下来的M行每行有两个整数c,w分别表示每种物品的重量和价值(0<c<100000,0<w<100000)
输出
对应每组测试数据输出结果(如果能恰好装满背包,输出装满背包时背包内物品的最大价值总和。 如果不能恰好装满背包,输出NO)
样例输入
2
1 5
2 2
2 5
2 2
5 1
样例输出
NO
1
#include<stdio.h>
#include<string.h>
int d[50001];
int main()
{
int n,i,j;
int c,v,a,b;
scanf("%d",&n);
while(n--)
{
scanf("%d%d",&c,&v);
memset(d,-11,sizeof(d));
d[0]=0;
for(i=0;i<c;i++)
{
scanf("%d%d",&a,&b);
for(j=a;j<=v;j++)
{
if(d[j]<d[j-a]+b)
d[j]=d[j-a]+b;
}
}
if(d[v]<0)
printf("NO\n");
else
printf("%d\n",d[v]);
}
return 0;
}
来源:https://www.cnblogs.com/yinyitianya/p/5425115.html