【刷题】【dp】地精的贸易

完全背包

难点:输出方案

wa点:m的范围在一次dp后,出现变化,导致re

#include<cstdio>
#include<cstdlib>
using namespace std;
int m,n;
const int N=103,M=1000003;
int a[N],b[N];

int f[2][M];//完全背包(压成一维) 
int pre[2][M];

int ans[N];
int main()
{
    //input
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
    //dp_0    
    for(int i=1;i<=n;i++)
    {
        int val=b[i]-a[i];//卖出价-买入价 
        if(val<=0) continue;
        for(int j=a[i];j<=m;j++)
            if(f[0][j] < f[0][j-a[i]]+val )
            {
                f[0][j]=f[0][j-a[i]]+val;
                pre[0][j]=i;
            }
    }
    int mm=m+f[0][m];
    //dp_1
    for(int i=1;i<=n;i++)
    {
        int val=a[i]-b[i];//卖出价-买入价 
        if(val<=0) continue;
        for(int j=b[i];j<=mm;j++)
            if(f[1][j] < f[1][j-b[i]]+val )
            {
                f[1][j]=f[1][j-b[i]]+val;
                pre[1][j]=i;
            }
    } 
    //find_way => get_excel
    int pos=m;
    while(pre[0][pos])
    {
        ans[pre[0][pos]]++;
        pos-=a[pre[0][pos]];
    }
    pos=mm;
    while(pre[1][pos])
    {
        ans[pre[1][pos]]++;
        pos-=b[pre[1][pos]];
    }
    //output
    printf("%d
",f[0][m]+f[1][mm]);
    for(int i=1;i<=n;i++)
    {
        printf("Buy %d",ans[i]);
        if(ans[i] )
            if(a[i]>b[i]) printf(" from Horde");
            else printf(" from Alliance");
        putchar('
');
    }
    
    return 0;
}
原文地址:https://www.cnblogs.com/xwww666666/p/11782475.html