2019 ICPC Malaysia National E. Optimal Slots 题解(01背包记录路径)

题目链接

题目大意

给你一个大小为 t 的背包和n个物品,每个物品的价值和质量相同,求你背包最多能装的价值,并且记录装了哪些物品,如果有多组解,你要尽可能装前面的物品,即使背包中物品的编号字典序最小

题目思路

如果只要求最大的价值,显然就是01背包裸题。而难点是要你记录背包中物品。其实就是回溯,具体见代码实现。一定要好好了解01背包的本质

代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
#define debug printf(" I am here\n");
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=2e3+5,inf=0x3f3f3f3f,mod=998244353;
const double eps=1e-10;
int t,n,v[maxn];
int dp[maxn][maxn];
signed main(){
    while(scanf("%d",&t)!=-1&&t){
        memset(dp,0,sizeof(dp));
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&v[i]);
        }
        reverse(v+1,v+1+n);//一定要注意翻转,保证字典序最小
        for(int i=1;i<=n;i++){
            for(int j=1;j<=t;j++){
                dp[i][j]=dp[i-1][j];
                if(v[i]<=j){
                    dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+v[i]);
                }
            }
        }
        int temp=t;
        for(int i=n;i>=1;i--){
            if(dp[i][temp]==dp[i-1][temp-v[i]]+v[i]){
                printf("%d ",v[i]);
                temp=temp-v[i];
            }
        }
        printf("%d\n",dp[n][t]);
    }
    return 0;
}

你可能感兴趣的:(dp)