分析:
一眼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;
}