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;
}
//
发布了554 篇原创文章 · 获赞 31 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/104274334