zoukankan      html  css  js  c++  java
  • UVA-624 CD (01背包+路径记忆)

    题意:给一个播音机(背包),然后给你一段播放时间n(容量),每个对应又m 个磁带,每个磁带都有自己的时间(容量),求能播放最长的时间以及输出所选择的磁带(能塞背包的最大体积以及选择的物品),每种磁带只能播放一次;

    思路:这便是0/1背包的题(物品只能使用一次),同时与之不同的是要 输出所选择的物品。我们就用二维dp来记录(一维不能记录到底最后选择的是哪个物品)

    如果dp[i][j]== dp[i-1][j-v[i]]+v[i],意味着这是恰好符合上次转移过来的路径,倒退最后就可以获得物品(由于是逆序得到物品,所以也要逆序输出)

    完整代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    const int maxn =1e5;
    int dp[30][maxn];
    int v[maxn];
    int ans[maxn];
    using namespace std;
    int main(){
        int n,m;
        while(~scanf("%d%d",&n,&m)){
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=m;i++){
                scanf("%d",&v[i]);
            }
            for(int i=1;i<=m;i++){
                for(int k= n;k>0;k--){
                    dp[i][k] += max(dp[i-1][k-v[i]]+v[i],dp[i-1][k]);
                    if(k<v[i]) dp[i][k] = dp[i-1][k];
                }
            }
            int cnt = 0;
            for(int i=m,j=n;i>0;i--){//下标与背包容量 
                if(j-v[i]>=0&&dp[i][j]== dp[i-1][j-v[i]]+v[i]){
                    ans[cnt++] = v[i];//从v[i]处推导来
                    j -= v[i]; 
                }
            }
            for(int i=cnt-1;i>=0;i--){
                cout<<ans[i]<<" ";
            }
            cout<<"sum:"<<dp[m][n]<<endl;
        
        }
    }

                                         

  • 相关阅读:
    adb、monkey常用命令
    震惊!90%的程序员不知道的Java知识!
    Android,重新出发!
    Fiddler 手机抓包 手机联网异常解决方案
    技术贴汇总
    Android开发日常-listview滚动方法梳理
    JavaScript基本语法
    Spring Boot Profile
    Spring Boot配置文件占位符
    @PropertySource和@ImportSource
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11223591.html
Copyright © 2011-2022 走看看