#include<cstring>
#include<iostream>
#include<algorithm>
#include<climits>
#define local
using namespace std;
int ci;
int T;
int n;
int t;
int a[100];
int dp[12000];
int main()
{
#ifdef local
freopen("C:\\Users\\sukieandxuan\\Desktop\\新建文件夹\\data.in", "r", stdin);
freopen("C:\\Users\\sukieandxuan\\Desktop\\新建文件夹\\data.out", "w", stdout);
#endif
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &n, &t);
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
memset(dp, -1, sizeof(dp));
a[n] = 678;
dp[0] = 0;
//printf("%d", minute);
for (int i = 0; i <= n; i++)
{
for (int j = t-1+a[i]; j >=a[i] ; j--)
{
if (dp[j-a[i]] != -1)
{
dp[j] = max(dp[j], dp[j-a[i]] + 1);
printf("%d %d\n", dp[j], j);
}
}
}
int max1 = INT_MIN, ans = 0;
for (int i = 10000; i >= 0; i--)
{
if (dp[i] != -1)
{
if (max1 < dp[i])
{
max1 = dp[i];
ans = i;
}
}
}
printf("Case %d: %d %d\n", ++ci, max1, ans);
}
return 0;
}
先贴代码。(ps:代码看起来长其实真正用到的很短233)
这道题一开始我以为就是简单的背包问题,结果发现读题不仔细,他要求时间最长我求出来时间最短。
思路:
利用滚动数组,假设从t+a[i]开始遍历,j-a[i]的值就可以从0- t-1取值,即满足小于t-1的要求。这里的dp为唱歌的歌曲数目,dp的下标为时间数。因为这里我把678也加入到了数组中,所以即便是之前例如 40 80 ,加起来为120超过了100,最后的40 80 678,也会选择40+678,因为不会遍历到120,而且歌曲数目也正好 40 80为2,40 80 678 也为2 。
最后说一说我这道题挂了10次,我一直觉得我算法没有问题,仔细一看发现我的t是用lld输入的,因为一开始以为t<=10^9,后来发现t<=9000,就不需要担心了。