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;
}

 

posted @ 2016-10-28 21:31  TianTengtt  阅读(144)  评论(0编辑  收藏  举报