UVa 12563

背包问题简单使用,利用滚动数组法能够实现,由于题目中还提到在歌曲数目相同的状况下尽量时间久,这时候就能够引入另外一个DP数组tdp记录策略所对应的歌曲时间。
须要注意的是,tdp的大小关系的定义:ios

  • dp[j-s[i]]+1> dp[j]时,没有争议,dp(i, j)状态时,应该选择第i首歌曲,tdp应该更新为相应策略的时间
  • dp[j-s[i]]+1== dp[j],争议出现,这时候选择tdp更小的那个策略
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cmath>
#include <vector>
using namespace std;

const int maxn= 55;
const int maxt= 180*maxn;
const int GJJ= 678;

int dp[maxt], tdp[maxt];
int s[maxn];

void Init(int t)
{
	for (int i= t; i> 0; --i){
		dp[i]= s[1]< i ? 1 : 0;
		tdp[i]= dp[i] ? GJJ+s[1] : GJJ;
	}
}

int main()
{
	int T, n, t, kase;

	scanf("%d", &T);
	for (kase= 1; kase<= T; ++kase){
		scanf("%d %d", &n, &t);
		for (int i= 1; i<= n; ++i){
			scanf("%d", s+i);
		}
		Init(t);

		for (int i= 2; i<= n; ++i){
			for (int j= t; j> 0; --j){
				if (s[i]>= j){
					continue;
				}
				if (dp[j-s[i]]+1> dp[j]){
					dp[j]= dp[j-s[i]]+1;
					tdp[j]= tdp[j-s[i]]+s[i];
				}
				else if (dp[j-s[i]]+1== dp[j] && tdp[j-s[i]]+s[i]> tdp[j]){
					tdp[j]= tdp[j-s[i]]+s[i];
				}
			}
		}
		printf("Case %d: %d %d\n", kase, dp[t]+1, tdp[t]);		
	}

	return 0;
}