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;
}
相關文章
相關標籤/搜索