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;
}