又见01背包

来源:互联网 发布:闪电VPN软件怎么样 编辑:程序博客网 时间:2024/05/09 10:23

又见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 52 31 23 42 2
样例输出
7

按照普通的01背包解法,肯定是不行的,即使一维坐标表示重量10^9,也太大了。所以可以考虑一下,如果价值固定,求出最小的重量,这样反过来求,就能a了,原理不难。

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cmath>#define N 210#define INF 1<<30using namespace std;int dp[N][N*N];int main(void){//freopen("题.txt", "r", stdin);int n, W, sumv = 0;int w[N],v[N];while(scanf("%d%d", &n, &W) != EOF){for(int i = 1; i <= n; i++){scanf("%d%d", &w[i], &v[i]);sumv += v[i];}for(int i = 1; i <= sumv; i++){dp[0][i] = INF;}dp[0][0] = 0;for(int i = 1; i <= n; i++){for(int j = 0; j <= sumv; j++){if(j < v[i]){dp[i][j] = dp[i-1][j];}else{dp[i][j] = min(dp[i-1][j], dp[i-1][j-v[i]] + w[i] );}}}int sum;for(int i = 0; i <= sumv; i++){if(dp[n][i] <= W){sum = i;}}printf("%d\n", sum);}return 0;}


0 0
原创粉丝点击