背包问题输出方案 ACWING 12

以ACWING 12题为例
https://www.acwing.com/problem/content/description/12/

方案输出问题要求从结果遍历
使用了4种方法输出
本题要求的是输出背包方案,并要求方案字典序最小。
因此要从后往前转移,并且等于的时候也要发生转移。

方案1:记录pre[i][j]代表状态(i,j)是否发生了转移。那么一旦pre[i][j]为1,就代表选择了i,就输出i,同时 j 减去背包容积
方案2:即为方案1的递归形式
方案3:记录的的pre[i][j]代表(i,j)状态时候的背包容积。如果背包容积小于j,说明背包发生了转移,输出i。
方案4:直接判断dp[i][j] 与 dp[i + 1][j - v[i]] + w[i] 的 关系。如果相等就说明发生了转移。并且要特判i = n时候的情况,此时只要容积大于v[n],就输出n。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;

const int mod = 1e9 + 7;
vector<int>ans;
int v[1005],w[1005];
int f[1005],pre[1005][1005],pre2[1005][1005];
int dp[1005][1005];
int n,m;

void Print1(int i,int j)
{
    if(i == n + 1)return;
    if(pre[i][j])
    {
        printf("%d %d\n",i,j);
        Print1(i + 1,j - v[i]);
    }
    else
    {
        Print1(i + 1,j);
    }
}

void Print2(int num)
{
    for(int i = 1;i <= n;i++)
    {
        if(pre[i][num])
        {
            printf("%d ",i);
            num -= v[i];
        }
    }
}

void Print3(int i,int j)
{
    if(i == n + 1)return;
    if(pre2[i][j] < j)
    {
        printf("%d ",i);
    }
    Print3(i + 1,pre2[i][j]);
}

void Print4()
{
    int j = m;
    for(int i = 1;i <= n;i++)
    {
        if(i == n && j >= v[i])
        {
            printf("%d\n",i);
            break;
        }
        if(dp[i][j] == dp[i + 1][j - v[i]] + w[i] && j >= v[i])
        {
            printf("%d ",i);
            j -= v[i];
        }
    }
}

void Zero1()
{
    for(int i = n;i >= 1;i--)
    {
        for(int j = m;j >= 0;j--)
        {
            pre2[i][j] = j;
            if(f[j] <= f[j - v[i]] + w[i] && j >= v[i])
            {
                pre[i][j] = 1;
                f[j] = f[j - v[i]] + w[i];
                pre2[i][j] = j - v[i];
            }
        }
    }
}

void Zero2()
{
    for(int i = n;i >= 1;i--)
    {
        for(int j = 0;j <= m;j++)
        {
            dp[i][j] = dp[i + 1][j];
            if(j >= v[i])
            {
                dp[i][j] = max(dp[i][j],dp[i + 1][j - v[i]] + w[i]);
            }
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++)
    {
        scanf("%d%d",&v[i],&w[i]);
    }
    Zero1();
    Zero2();
    
    Print1(1,m);
//    Print2(m);
//    Print3(1,m);
//    Print4();
    return 0;
}

发布了676 篇原创文章 · 获赞 18 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/104254359
今日推荐