UVA - 12563 - Jin Ge Jin Qu hao(01背包)
题意:KTV在时间结束后不立即停止,而是把你目前在唱的这首歌唱完再停止。假如你在KTV还剩 t 秒的时间(1 <= t <= 10^9),你有 n 首歌可以选(1 <= n <= 50),n首歌分别给出每首歌的时间(最多180秒),现在你最后唱的歌必须是固定的不在 n 首歌之中的一首678秒的歌,求最多能唱多少首歌,以及在包房待的总时间(如果歌数相同则要求离开时间尽量晚)。
01背包问题,在时间的限制下,要让唱的歌数以及所待的总时间尽量长。
d[i],代表,从开始时间起到第 i 时刻总共唱的歌的数量,与其同步的是num[i]代表总共唱的歌的时间。
这里的时刻最多为180 * n(不算最后的678的歌),所以数组的上限最多为180 * 50 = 9000,而在枚举时刻的时候则可以缩小枚举范围到0 ~ Min(t - 1, 180 * n); (t - 1的原因是:至少要留出来一秒开始唱最后678的歌)。
代码如下:
#include<cstdio> #include<cstring> #include<cctype> #include<cstdlib> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<deque> #include<queue> #include<stack> #include<list> #define fin freopen("in.txt", "r", stdin) #define fout freopen("out.txt", "w", stdout) #define pr(x) cout << #x << " : " << x << " " #define prln(x) cout << #x << " : " << x << endl #define Min(a, b) a < b ? a : b #define Max(a, b) a < b ? b : a typedef long long ll; typedef unsigned long long llu; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const ll LL_INF = 0x3f3f3f3f3f3f3f3f; const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f; const double pi = acos(-1.0); const double EPS = 1e-6; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const ll MOD = 1e9 + 7; using namespace std; #define NDEBUG #include<cassert> const int MAXN = 50 + 10; const int MAXT = 10000 + 10; int T, n, t; int d[MAXT], num[MAXT]; int main(){ scanf("%d", &T); for(int kase = 1; kase <= T; ++kase){ scanf("%d%d", &n, &t); memset(d, 0, sizeof d); memset(num, 0, sizeof num); for(int i = 1; i <= n; ++i){ int time; scanf("%d", &time); for(int j = Min(t - 1, 180 * n); j >= 0; --j) if(j >= time){ if(d[j - time] + 1 > d[j]){ d[j] = d[j - time] + 1; num[j] = num[j - time] + time; } else if(d[j - time] + 1 == d[j]) num[j] = Max(num[j], num[j - time] + time); } } int len = Min(t - 1, 180 * n); int songnum = -1, songtime = 0; for(int j = len; j >= 0; --j){ if(d[j] > songnum){ songnum = d[j]; songtime = num[j]; } else if(d[j] == songnum) songtime = Max(songtime, num[j]); } printf("Case %d: %d %d\n", kase, songnum + 1, songtime + 678); } return 0; }