1. 程式人生 > >2097 Problem I 畢業bg

2097 Problem I 畢業bg

問題 I: 畢業bg

時間限制: 1 Sec  記憶體限制: 32 MB
提交: 61  解決: 20
 

題目描述

每 年畢業的季節都會有大量畢業生髮起狂歡,好朋友們相約吃散夥飯,網路上稱為“bg”。參加不同團體的bg會有不同的感覺,我們可以用一個非負整數為每個 bg定義一個“快樂度”。現給定一個bg列表,上面列出每個bg的快樂度、持續長度、bg發起人的離校時間,請你安排一系列bg的時間使得自己可以獲得最 大的快樂度。

例如有4場bg:
第1場快樂度為5,持續1小時,發起人必須在1小時後離開;
第2場快樂度為10,持續2小時,發起人必須在3小時後離開;
第3場快樂度為6,持續1小時,發起人必須在2小時後離開;
第4場快樂度為3,持續1小時,發起人必須在1小時後離開。
則獲得最大快樂度的安排應該是:先開始第3場,獲得快樂度6,在第1小時結束,發起人也來得及離開;再開始第2場,獲得快樂度10,在第3小時結束,發起人正好來得及離開。此時已經無法再安排其他的bg,因為發起人都已經離開了學校。因此獲得的最大快樂度為16。

注意bg必須在發起人離開前結束,你不可以中途離開一場bg,也不可以中途加入一場bg。
又因為你的人緣太好,可能有多達30個團體bg你,所以你需要寫個程式來解決這個時間安排的問題。

輸入

測試輸入包含若干測試用例。每個測試用例的第1行包含一個整數N (<=30),隨後有N行,每行給出一場bg的資訊:
    h l t
其中 h 是快樂度,l是持續時間(小時),t是發起人離校時間。資料保證l不大於t,因為若發起人必須在t小時後離開,bg必須在主人離開前結束。

當N為負數時輸入結束。

輸出

每個測試用例的輸出佔一行,輸出最大快樂度。

樣例輸入

3
6 3 3
3 2 2
4 1 3
4
5 1 1
10 2 3
6 1 2
3 1 1
-1

樣例輸出

7
16

經驗總結

這一題。。。愣是沒看懂題目在說什麼。。。網上搜了一下別人的程式碼,才知道,這竟然是經典的01揹包 0.0 真的沒看出來啊。。。不過我就按照01揹包的自己理解一下,發起人必須在幾小時後離開,這就相當於揹包的體積,即在這幾個小時裡,可以安排多少場bg,以獲得最大的快樂度,然後持續時間,相當於一個物品的容積,快樂度相當於物品的價值,但是,在實現狀態轉移方程時注意一點,雖然題目說了,每場bg的 l 不可能大於 t ,所以,要從 bg[ i ] . l 訪問到 b [ i ]. t。在進行訪問之前要對所有bg按照發起人離開時間 t 從小到大進行排序,原因。。。不是很清楚- -  知道原因的大佬可以評論告訴我咩?謝謝啦~
還有邊界別按照常理覺得持續時間怎麼可能超過24小時呢?但實際後臺測試資料確實不止24.。40都不止= =。一定注意測試資料可不按常理出牌,往大了定義。

正確程式碼

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=1000;
int dp[maxn];
struct BG
{
	int h,l,t;
}bg[maxn];
 
bool cmp(const BG a,const BG b)
{
	return a.t<b.t;
}
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		if(n<0)
			break;
		int max1=0;
		for(int i=1;i<=n;++i)
		{
			scanf("%d %d %d",&bg[i].h,&bg[i].l,&bg[i].t);
			if(bg[i].t>max1)
				max1=bg[i].t;
		}
		sort(bg+1,bg+n+1,cmp);
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;++i)
		{
			for(int j=bg[i].t;j>=bg[i].l;--j)
			{
				dp[j]=max(dp[j],dp[j-bg[i].l]+bg[i].h);
			}
		}
		int result=dp[max1];
		for(int j=max1;j>=1;--j)
			if(result<dp[j])
				result=dp[j];
		printf("%d\n",result);
	}
	return 0;
}