http://49.235.120.161/problem/10031
题意:N个物品 选每个物品i 将用时si+di 花费vi元 获得价值为1
问N个物品 总时间为T 钱包有M元 获得的最大价值Ans与Ans的方案数
N<=1000 T,M<=100
正着做:
ll dp[1005][105][105]; 前i个物品 花时间至多j,花钱至多k的最大价值
ll dp2[1005][105][105];前i个物品 花时间至多j,花钱至多k的最大价值的方案数
注意dp2计算方案数是要初始化的
dp转移就是01背包嘛,就是选/不选的状态都枚举,哪个大选哪个
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
int N,T,M;
ll si[1005];
ll di[1005];
ll vi[1005];
ll dp[1005][105][105];//i
ll dp2[1005][105][105];//
int main(){
cin>>N>>T>>M;
for(int i=1;i<=N;i++)cin>>si[i]>>di[i]>>vi[i];
memset(dp,0,sizeof(dp));
memset(dp2,0,sizeof(dp2));
for(int j=0;j<=M;j++){
for(int k=0;k<=T;k++){
dp2[0][j][k]=1;
}
}
for(int i=1;i<=N;i++){
for(int j=0;j<=M;j++){
for(int k=0;k<=T;k++){
if(j>=vi[i]&&k>=si[i]+di[i]){
if(dp[i-1][j][k]<dp[i-1][j-vi[i]][k-si[i]-di[i]]+1){
dp[i][j][k]=dp[i-1][j-vi[i]][k-si[i]-di[i]]+1;
dp2[i][j][k]=dp2[i-1][j-vi[i]][k-si[i]-di[i]]%mod;
}
if(dp[i-1][j][k]==dp[i-1][j-vi[i]][k-si[i]-di[i]]+1){
dp[i][j][k]=dp[i-1][j][k];
dp2[i][j][k]=(dp2[i-1][j-vi[i]][k-si[i]-di[i]] +dp2[i-1][j][k])%mod;
}
if(dp[i-1][j][k]>dp[i-1][j-vi[i]][k-si[i]-di[i]]+1){
dp[i][j][k]=dp[i-1][j][k];
dp2[i][j][k]=dp2[i-1][j][k]%mod;
}
}
else{
dp[i][j][k]=dp[i-1][j][k];
dp2[i][j][k]=dp2[i-1][j][k];
}
}
}
}
ll ans1=dp[N][M][T],ans2=dp2[N][M][T];
cout<<ans1<<" "<<ans2%mod<<endl;
}
反着做:(滚动)但dp2的定义不同了,为恰好使用(前面是至多),dp1不变
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
const int MOD=1e9+7;
int n,m,t,s[N],d[N],v[N];
int dp1[110][110],dp2[110][110];
int main()
{
freopen("4.in","r",stdin);
//freopen("7.out","w",stdout);
cin>>n>>t>>m;
for (int i=1;i<=n;i++) scanf("%d%d%d",&s[i],&d[i],&v[i]);
for (int i=1;i<=n;i++) s[i]+=d[i];
memset(dp1,-0x3f,sizeof(dp1));
memset(dp2,-0x3f,sizeof(dp2));
dp1[0][0]=0; dp2[0][0]=1;
for (int i=1;i<=n;i++)
for (int j=t;j;j--)
for (int k=m;k;k--) {
if (j<s[i] || k<v[i]) continue;
if (dp1[j-s[i]][k-v[i]]+1>dp1[j][k]) {
dp1[j][k]=dp1[j-s[i]][k-v[i]]+1;
dp2[j][k]=dp2[j-s[i]][k-v[i]];
} else if (dp1[j-s[i]][k-v[i]]+1==dp1[j][k]) {
dp2[j][k]+=dp2[j-s[i]][k-v[i]];
dp2[j][k]%=MOD;
}
}
int ans1=0,ans2=0;
for (int j=0;j<=t;j++) for (int k=0;k<=m;k++)
if (dp1[j][k]>ans1) ans1=dp1[j][k],ans2=dp2[j][k];
else if (dp1[j][k]==ans1) ans2=(ans2+dp2[j][k])%MOD;
cout<<ans1<<" "<<ans2<<" "<<dp1[t][m]<<" "<<dp2[t][m]<<endl;
return 0;
}