UVA - 12563 劲歌金曲(DP 01背包)

题目

KTV里面有n首歌曲你可以选择,每首歌曲的时长都给出了(每首歌时长不超过3min). 对于每首歌曲,你最多只能唱1遍. 现在给你一个时间限制t (t<=10^9) , t实际不会超过(180n+678)问你在最多t-1秒的时间内可以唱多少首歌曲num , 且最长唱歌时间是多少time 最终输出num+1 和 time+678 即可(最后唱一首“劲歌金曲”).

你需要优先让歌曲数目最大的情况下,再去选择总时长最长的.

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <map>
#include <vector>
#include <string.h>
#include <string>
#include <queue>
#include <set>
using namespace std;
//ios_base::sync_with_stdio(false);
//#include <bits/stdc++.h>
typedef long long ll;

int a[100];
int dp[100][10100]; //歌曲时间
int q[100][10100]; //歌曲数目
int main()
{
    int T, cas = 0;
    scanf("%d", &T);
    while(T--)
    {
        int n, t;
        scanf("%d%d", &n, &t);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
        }
        for(int i = 1; i <= n; i++)
        {
            for(int j = t; j >= 0; j--)
            {
                dp[i][j] = (i == 1 ? 0 : dp[i-1][j]);
                q[i][j] = (i == 1 ? 0 : q[i-1][j]);
                if(j > a[i])
                {
                    //按歌曲数目优先
                    if(q[i][j] < q[i-1][j-a[i]]+1)
                    {
                        dp[i][j] = dp[i-1][j-a[i]]+a[i];
                        q[i][j] = q[i-1][j-a[i]]+1;
                    }
                    //歌曲数目相等,就按歌曲时间长度
                    else if(q[i][j]==q[i-1][j-a[i]]+1)
                        dp[i][j]=max(dp[i][j],dp[i-1][j-a[i]]+a[i]);

                }
            }
        }
        printf("Case %d: %d %d\n", ++cas, q[n][t]+1, dp[n][t]+678);

    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qihang_qihang/article/details/81153567