UVA12563(两个权值一起考虑)

这道题目可以套用0-1背包的模型,其中剩余时长-1就是背包的总容量,而在这些时间内,能唱的最多的歌曲数,就是背包问题的重量

cnt[i][j]的定义就是在时长还剩下j秒的时候,在前i首歌中挑选,最多能够唱几首

但是值得一提的是,这里面还有另外一个权值,就是时长;

即如果能唱的歌曲数相同,挑选时长最大的。

值得一提的是,如果不用去管cnt,只去管能唱的时间长度,那么d[i][j]的定义为,在时长还剩j秒时,在前i首歌中挑选,最多能够唱几首歌。此时的重量,就是时间。

在这道题中遇到的bug是,没有考虑到时间的最大值,将数组开小了

下面是代码

#include<cstdio>
#include<algorithm>
using namespace std;
//d[i][j] j秒内,唱前i首歌,可以唱的最多的时间数
//和0-1背包问题的相似之处在于,歌的时间既是重量又是体积
const int maxn = 102;
const int maxt = 10000;

int d[maxn][maxt];
int cnt[maxn][maxt];

int num_song;
int time_left;//计算在time_left - 1的时间内
int time[maxn];//每一首歌对应的时间

int main()
{
#ifdef local
    freopen("input.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    int T;
    scanf("%d",&T);
    for(int i = 0;i < T;i++)
    {
        scanf("%d%d",&num_song,&time_left);
        for(int j = 1;j <= num_song;j++)//弃用0
        {
            scanf("%d",&time[j]);
        }
        for(int k = 1;k <= num_song;k++)
        {
            for(int j = 0;j <= time_left - 1;j++)
            {
                d[k][j] = (k == 1? 0:d[k - 1][j]);
                cnt[k][j] = (k == 1? 0:cnt[k - 1][j]);
                if(j >= time[k])
                {
                    if(cnt[k][j] < cnt[k - 1][j - time[k]] + 1)
                    {
                        cnt[k][j] = cnt[k - 1][j - time[k]] + 1;
                        d[k][j] = d[k - 1][j - time[k]] +time[k];
                    }
                    else if(cnt[k][j] == cnt[k - 1][j - time[k]] + 1)
                    {
                        if(d[k][j] < d[k - 1][j - time[k]] +time[k])
                        {
                            d[k][j] = d[k - 1][j - time[k]] + time[k];
                        }
                    }
                }
            }
        }
        printf("Case %d: %d %d\n",i+1,cnt[num_song][time_left - 1] + 1,d[num_song][time_left - 1] + 678);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/TorettoRui/p/10482195.html