Tyvj1013

题目链接

分析:
一眼dp
如果没有要求时间最短那么一个二维背包就可以解决了
但是有了时间的限制,这就相当于在保存最大解的时候
记录一下花费,如果有不同状态可以转移到最大解
我们就保留一个最优解

这就是一个比较特殊的dp了
需要两个限制都达到最优
一般情况下都是把一个限制加入dp的维度中
直接进行dp
但是这样的复杂度是O(n^4)的,显然不行
那我们就需要把原先的一个f(状态转移方程)
变成两个(f,F),
f只维护最大数量
F在f的前提下维护最小花费

tip

if (f[j][k]<f[j-rmb[i]][k-rp[i]]+1)
{
    f[j][k] = f[j-rmb[i]][k-rp[i]]+1;
    F[j][k] = F[j-rmb[i]][k-rp[i]]+t[i]; 
}

这里的状态转移还是有一点细节的,
如果最大值更改
那么F直接添加
还有这个判断也很有意思

f[j][k] < f[j-rmb[i]][k-rp[i]]+1
把相等的情况排除,因为相等时我们需要维护最小花费

这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

int f[101][101],F[101][101];
int t[101],rmb[101],rp[101],M,R,n,mx=0,ans=10000000;

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        scanf("%d%d%d",&rmb[i],&rp[i],&t[i]);
    scanf("%d%d",&M,&R);
    for (int i=1;i<=n;i++)
        for (int j=M;j>=rmb[i];j--)
            for (int k=R;k>=rp[i];k--)
            {
                if (f[j][k]<f[j-rmb[i]][k-rp[i]]+1)
                {
                    f[j][k]=f[j-rmb[i]][k-rp[i]]+1;
                    F[j][k]=F[j-rmb[i]][k-rp[i]]+t[i];   //这种情况下直接加 
                }
                else
                {
                    if (f[j][k]==f[j-rmb[i]][k-rp[i]]+1)
                       F[j][k]=min(F[j][k],F[j-rmb[i]][k-rp[i]]+t[i]);
                }
                if (f[j][k]>mx) mx=f[j][k],ans=F[j][k];
                else if (f[j][k]==mx) ans=min(ans,F[j][k]);
            }
    if (ans==10000000) printf("0");
    else printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/wutongtong3117/p/7673353.html