动态规划--九度1123.[采药]

【2017/3/2】
【题目:http://ac.jobdu.com/problem.php?pid=1123

【后附加 滚动数组 改进】

/**********************3stone*********************************
FileName: 九度.1123.采药 
Author:3stone
Time:2017/3/2
题意:0-1背包问题【每种物品只有一个】

dp[i][j]:表示前i件物品恰好装入容量为j的背包中所能所得的最大价值
【由于j是恰好,所以需要枚举j属于[0-V]时 dp[n][j],取其最大值;
显然九度测试点没有考察到这一点,最后直接输出dp[n][V]也能AC】


状态分支:每一件物品加入与否

状态转移方程:dp[i][j] =  max(dp[i-1][j], dp[i-1][j-w[i]]+c[i])

边界:dp[0][j] = 0 【前0件物品放进任何容量的背包,所获价值都只能为0】 

注意:若 j<w[i] 即表示背包容量比这个物品还小,无法装入 

***********************3stone***********************************/
#include<cstdio>
#include<algorithm>
#define INF 0x7fffffff
using namespace std;

struct E{
    int w; //花费 
    int v;//价值 
}list[110];

int dp[110][1010]; //前i件物品恰好装入容量为j的背包中所能所得的最大价值

int main(){
    int t, m;
    while(scanf("%d%d", &t, &m) != EOF){

        for(int i = 1; i <= m; i++){
            scanf("%d%d", &list[i].w, &list[i].v);
        }

        for(int i=0; i<=t; i++) dp[0][i] = 0;//边界 

        int ans = 0;        
        for(int i=1; i<=m; i++){//遍历每一个物品 
            for(int j=t; j>=list[i].w; j--){//每一种容量 

                dp[i][j] = max(dp[i-1][j], 
                                dp[i-1][j-list[i].w]+list[i].v);                    
            }

            for(int j = list[i].w-1; j>=0;j--){
            //list[i].w>j表示此物品体积大于背包容量,无法装入,
              只能由dp[i-1][j]而来
                dp[i][j] = dp[i-1][j];
            }
        }
        printf("%d\n", dp[m][t]);
    } 
    return 0;
}

【使用滚动数组降低空间复杂度】

#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x7fffffff
using namespace std;
struct E{
    int w;
    int c;
}list[110];

int dp[110];//使用一维数组保存结果,因为d[i][j]只用到了
        //dp[i-1][j] 和dp[i-1][j-list[i].w],可以覆盖保存

int main(){
    int V, n;
    while(scanf("%d%d", &V, &n) != EOF){
        for(int i = 1;i <= n; i++){
            scanf("%d%d", &list[i].w, &list[i].c);
        }

        for(int i=0; i<=V; i++) dp[i] = 0;//边界

        for(int i=1; i<=n; i++){//主要变动;必须逆序遍历V,保证要用到的       
            (int j=V;j>=list[i].w;j--){//dp[j-list[i]]没被本轮修改
                dp[j]= max(dp[j], dp[j-list[i].w] + list[i].c);
            }
        }

        int max = 0;//并非恰好装满 
        for(int i=1;i<=V;i++){
            if(max<dp[i])
                max = dp[i];    
        }
        printf("%d\n", max);
    }

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值