UVA 12563 勁歌金曲 01揹包

2022-03-10 22:33:59 字數 1508 閱讀 2361

【題目鏈結】勁歌金曲

【題目型別】01揹包

&題解:

題意:求在給定時間內,最多能唱多少歌曲,在最多歌曲的情況下,使唱的時間最長。

該題類似於01揹包問題,可用01揹包問題的解題思路來求,每個歌曲相當於物品,歌曲的長度相等於物品重量,每個歌曲的「價值」為1。由於金歌勁曲時間最長,所以最後要留至少1秒時間開始唱金歌勁曲,所以計算t-1時間內最多唱的歌曲和時間,最終答案為歌曲數加1,時間加上金歌勁曲的時間。這裡我使用滾動陣列計算這個值, 用len記錄t-1。

需要注意的是,由於要求是連續唱歌,且要求在最多歌曲數的情況下時間最長,如果按普通的揹包儲存,很難得到最長時間,因為f[len] 只儲存了最多的歌曲數,但並不知道這些歌曲到底唱了多少時間。假設最多歌曲數為num, 唱num首歌曲最少時間為tmin, 那麼陣列中從f[tmin]到f[len]都等於num,我們無法得知唱num首歌的最大時間。比如說len = 10, t[1] = 5, t[2] = 8, 那麼f[5] 到 f[10] 都等於1, 無法知道唱從5到10哪個是唱1首歌的最長時間。如何處理呢?

這裡需要用到乙個技巧:對決策進行一定的限定!在計算某個時間最多唱的歌曲時,必須是該時間內恰好唱完這些歌,時間多了不行。即f[j]表示的是在j 的時間恰好用完的情況下最多能唱多少首歌。比如上面的例子只有f[5] 和f[8]等於1,其他的都等於0。這樣的話處理時先算出最多唱的歌曲數 num,然後從j = len開始遍歷陣列f, 第乙個等於num的就是在最多歌曲情況下的最長時間。

參考於:

這是01揹包的變形,但上面的想法確實很巧妙,也就是巧妙在定義f陣列所表示的狀態的時候,真的應該學習下這種分析問題的過程。

【時間複雜度】o(n*10000)

&**:

#include using namespace std;

typedef long long ll;

const int inf = 0x3f3f3f3f;

#define cle(a,val) memset(a,(val),sizeof(a))

#define si(n) scanf("%d",&(n))

#define sii(n,m) scanf("%d %d",&(n),&(m))

#define siii(n,m,k) scanf("%d %d %d",&(n),&(m),&(k))

#define rep(i,b) for(int i=0;i<(b);i++)

#define rez(i,a,b) for(int i=(a);i<=(b);i++)

#define red(i,a,b) for(int i=(a);i>=(b);i--)

const ll linf = 0x3f3f3f3f3f3f3f3f;

#define pu(x) puts(#x);

#define pi(a) cout<<(a)<>t;while(t--)

solve();

return 0;

}

uva 12563 勁歌金曲

題目大意 你在ktv唱歌,有乙個時限,但是在時限到時,若一首歌沒唱完可以繼續唱,已知有n首歌可以唱,已知他們的時長每個都不超過3分鐘 不能重複唱一首歌。還有一首678秒的歌,歌之間可以無縫銜接 思路 典型的揹包問題 求這n首歌能達到不超過t 1的時間 t 1是因為要留出1秒來開始那個巨長的歌 1 i...

UVA 12563 揹包問題的注意問題

這道題就是揹包問題。但是我在一維陣列 滾動陣列 和二維陣列上沒理解清楚,導致出現了bug,找了好久才想出來。二維陣列做法 include include include include include include include include include include include u...

UVa 12563(一種錯誤做法和一種正確做法)

題意 求在給定時間內,最多能唱多少歌曲,在最多歌曲的情況下,使唱的時間最長。該題類似於01揹包問題,可用01揹包問題的解題思路來求,每個歌曲相當於物品,歌曲的長度相等於物品重量,每個歌曲的 價值 為1。由於金歌勁曲時間最長,所以最後要留至少1秒時間開始唱金歌勁曲,所以計算t 1時間內最多唱的歌曲和時...