稍微转换一下就是01背包问题。值得注意的是,这里要先保证唱的歌数最多,其次是唱的时间越长。我在这里用了分情况讨论:
1.不唱这首歌,总歌数多一点,则不唱这首歌
if(dp[t][0]>dp[t-ge][0]+1){
continue;
}
2.唱这首歌,不唱这首歌,总歌数一样,则更新唱歌时间
else if(dp[t][0]==dp[t-ge][0]+1){
dp[t][1]=max(dp[t-ge][1]+ge,dp[t][1]);
}
3.唱这首歌,总歌数多一点,则唱这首歌
else{
dp[t][0]=dp[t-ge][0]+1;
dp[t][1]=dp[t-ge][1]+ge;
}
但是这种情况对空间要求很多(因为t<1e9)正常情况下这个不行。但是看了刘汝佳书上的,t<180n+678,所以勉强可以。
#include<bits/stdc++.h>
using namespace std;
int dp[180*50+700][2];
int main(void){
int t;
scanf("%d",&t);
for(int kase=1;kase<=t;kase++){
int n,T;
memset(dp,0,sizeof(dp));
scanf("%d %d",&n,&T);
for(int i=1;i<=n;i++){
int ge;
scanf("%d",&ge);
for(int t=T-1;t>=0;t--){
if(t-ge>=0){
if(dp[t][0]>dp[t-ge][0]+1){
continue;
}
else if(dp[t][0]==dp[t-ge][0]+1){
dp[t][1]=max(dp[t-ge][1]+ge,dp[t][1]);
}
else{
dp[t][0]=dp[t-ge][0]+1;
dp[t][1]=dp[t-ge][1]+ge;
}
}
}
}
printf("Case %d: %d %d\n",kase,dp[T-1][0]+1,dp[T-1][1]+678);
}
}