UVa 12563
背包问题简单使用,利用滚动数组法可以实现,因为题目中还提到在歌曲数目相同的情况下尽可能时间久,这时候就可以引入另一个DP数组tdp记录策略所对应的歌曲时间。
需要注意的是,tdp的大小关系的定义:
- 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;
}