本题有两个状态,按照01背包方式进行状态转移即可,代码压了维,01背包倒着枚举,
难点主要在路径输出,还要求最小路径
首先看路径输出,设置string 类型的ans数组,ans[i][j]对应dp[i][j]的方案,状态转移时一并转移到ans数组即可。
if(dp[j][k]<=dp[j-g[i]][k-f[i]]+t[i])
{
dp[j][k]=dp[j-g[i]][k-f[i]]+t[i];
ans[j][k]=ans[j-g[i]][k-f[i]]+char(i);
}
再看最小路径,即相同获利,输出最小的,
把上面代码等号去掉即可,why?因为既然出现了等于的情况,就说明在i之前已经有比i更小的i出现了,并且满足了情况,所以只需要不断更新最优情况即可,无法更新时就是最后答案
另外,答案的输出要转化成整形;
#include<iostream>
#include<set>
# include<algorithm>
# include<cstring>
using namespace std;
typedef long long int ll;
int dp[210][210];
int g[110],f[110],t[110];
int G,F,n;
string ans[210][210];
int main()
{
cin>>G>>F>>n;
for(int i=1;i<=n;i++)
{
cin>>g[i]>>f[i]>>t[i];
}
for(int i=1;i<=n;i++)
{
for(int j=G;j>=g[i];j--)
{
for(int k=F;k>=f[i];k--)
{
if(dp[j][k]<dp[j-g[i]][k-f[i]]+t[i])
{
dp[j][k]=dp[j-g[i]][k-f[i]]+t[i];
ans[j][k]=ans[j-g[i]][k-f[i]]+char(i);
}
}
}
}
cout<<dp[G][F]<<endl;
for(int i=0;i<ans[G][F].length();i++)
{
cout<<(int)ans[G][F][i]<<" ";
}
return 0;
}