你有n首喜欢唱的歌,你要争取在t时间内唱最多的歌,数量相同时时间最长,最后唱一首劲歌金曲。
因为歌的总长度大于t,所以t比给出的范围小很多。用数组d[i][j]表示唱i首歌,剩余时间还有j秒时还能唱的歌数量,len[i][j]表示此时的时长,然后用01背包的方式解答。注意数量相同时要保证时长最长。
写的时候手滑把一个i和j写混了,改了一个小时……
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int d[55][10000];
int len[55][10000];
int main()
{
int T,kase=0;
int t,n,time[55];
cin>>T;
while(T--)
{
memset(d,0,sizeof(d));
memset(len,0,sizeof(len));
cin>>n>>t;
for(int i=1;i<=n;i++)
cin>>time[i];
for(int i=n;i>=1;i--)
{
for(int j=1;j<=t;j++)
{
d[i][j]=d[i+1][j];
len[i][j]=len[i+1][j];
if(j>time[i])
{
if(d[i][j]<d[i+1][j-time[i]]+1)
{
d[i][j]=d[i+1][j-time[i]]+1;
len[i][j]=len[i+1][j-time[i]]+time[i];
}
else if(d[i][j]==d[i+1][j-time[i]]+1)
len[i][j]=max(len[i][j],len[i+1][j-time[i]]+time[i]);
}
}
}
/*for(int i=n;i>=1;i--)
{
for(int j=1;j<=t;j++)
{
d[i][j]=d[i+1][j];
len[i][j]=len[i+1][j];
if(j>time[i])
{
if(d[i][j]<d[i+1][j-time[i]]+1)
{
d[i][j]=d[i+1][j-time[i]]+1;
len[i][j]=len[i+1][j-time[i]]+time[i];
}
else if(d[i][j]==d[i+1][j-time[i]]+1)
len[i][j]=max(len[i][j],len[i+1][j-time[i]]+time[i]);
}
}
}*/
printf("Case %d: %d %d\n",++kase,d[1][t]+1,len[1][t]+678);
}
return 0;
}