Gym 102219 E Optimal Slots —— 记录路径的01背包

This way

题意:

现在有一个大小为m的背包,现在有n个物品,告诉你每个物品的大小。现在要让你选一些物品使得这个背包的空余空间最小,并且你选的物品下标的字典序最小。

题解:

设dp[i][j]表示i必选的时候,当前背包大小为j的时候
首先如何记录路径,那么对于这种问题,大小就是它的价值,假设最大的答案为mx,那么如果dp[x][mx]=mx的话,那么一定选x的时候,能够达到mx,然后确定选x的时候,mx-=a[x],也就是上一个位置的时候的大小。这样依次下去就是路径
接下来是字典序最小。那么很明显路径从小到大去走才行。但是背包一定是从大到小的去判断是否是答案中的一种,那么解决方案就是从后往前dp即可。

#include<bits/stdc++.h>
using namespace std;
const int N=55;
int dp[N][N],a[N];
int main()
{
    int n,m;
    while(scanf("%d",&m)){
        if(!m)
            break;
        scanf("%d",&n);
        memset(dp,0,sizeof(dp));
        int mx=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=n;i>=1;i--){
            for(int j=m;j>=a[i];j--){
                for(int k=i+1;k<=n+1;k++)
                dp[i][j]=max(dp[i][j],dp[k][j-a[i]]+a[i]),mx=max(mx,dp[i][j]);
            }
        }
        int now=1,ans2=mx;
        while(mx){
            for(int i=now;i<=n;i++){
                if(dp[i][mx]==mx){
                    printf("%d ",a[i]);
                    now=i+1;
                    mx-=a[i];
                    break;
                }
            }
        }
        printf("%d\n",ans2);
    }
    return 0;
}
//
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值