Uva 12563 - Jin Ge Jin Qu(01背包)

题目链接 https://cn.vjudge.net/problem/UVA-12563

【题意】
KTV有规定,当时间到的时候不会把正在唱的歌切掉,而是会等它放完。现在有一首时长为678秒的劲歌金曲,假设你在唱KTV,还有t秒时间,接下来你要唱n首歌(不含劲歌金曲),然后在时间结束之前再唱一首劲歌金曲,使得唱歌总曲目最多的情况下,你离开KTV的时间尽量晚。

【输入格式】
输入整数T,共有T组输入数据,每组输入n(n <= 50),t(t <= 1e9)和每首歌的长度(不超过3分钟)。保证这n+1首歌的总长大于t。

【输出格式】
输出数据组数,唱的总曲目数和时间总长度。

【思路】
01背包问题的变型,抽象成背包问题,背包的总重为t-1,因为至少要留下1秒来唱最后的劲歌金曲。首先一首歌对应一件物品,物品的权值和重量都是输入中每首歌的时间,然后约束条件有两个,首先要满足尽可能地将更多的物品加入到背包中,其次要满足物品的价值尽量大。注意数据范围,虽然t<=1e9,但是因为保证n+1首曲子的时间大于t,所以t<180n+678

#include<bits/stdc++.h>
using namespace std;

const int maxn=15000;

int n,w;
int v[maxn];

struct node{
    int p,c;
    node(int pp=0,int cc=0):p(pp),c(cc){}
}dp[maxn];

int main(){
    cin.tie(0);
    ios_base::sync_with_stdio(0);
    int T;
    cin>>T;
    for(int kase=1;kase<=T;++kase){
        cin>>n>>w;
        for(int i=0;i<w;++i) dp[i]=node(0,0);
        for(int i=0;i<n;++i) cin>>v[i];

        for(int i=0;i<n;++i){
            for(int j=w-1;j>=v[i];--j){
                if(dp[j].c<dp[j-v[i]].c+1){
                    dp[j].c=dp[j-v[i]].c+1;
                    dp[j].p=dp[j-v[i]].p+v[i];
                }
                else if(dp[j].c==dp[j-v[i]].c+1 && dp[j].p<dp[j-v[i]].p+v[i]){
                    dp[j].p=dp[j-v[i]].p+v[i];
                }
            }
        }
        printf("Case %d: %d %d\n",kase,dp[w-1].c+1,dp[w-1].p+678);
    }
    return 0;
}
posted @ 2018-03-26 19:27  不想吃WA的咸鱼  阅读(141)  评论(0编辑  收藏  举报