POJ 1036 Gangsters -- 常規dp 題意好難懂啊

/*
	http://poj.org/problem?id=1036  Gangsters
翻譯: N  個盜賊去一個飯店,第i個盜賊在Ti時間來,他擁有Pi的財富。這個飯店的門有

K+1種開放的狀態,用[0,K]表示。這些狀態能夠被一個盜賊改變在一個時間單位內,要麼把

它打開,要麼把它關閉,或者就是維持原狀。在初始時刻這些門都是關閉着的。第i個盜賊

進入了飯店僅當這個門是專門爲他所開放的時候,也就是說這個門的狀態與他的堅強程度Si

一致的時候。當盜賊來到飯店的這一刻,如果開放的狀態不等於盜賊的堅強程度的時候,這

個盜賊就不會再來了。
飯店的工作時間爲區間[0,T]
目標是幫 盜賊在飯店裏收集到最大的財富,通過恰當的打開或者關閉門。

思路:按照時間將盜賊排序,排在前面的盜賊先進飯店,我們知道如果時間一旦進過了某給點,那麼那個時候的盜賊所能產生的價值已經固定了,後來的不會對他的價值有影響了,因此我們只需要循環枚舉一下這些盜賊的組合即可算出最大價值。

4 10 20
10 16 8 16
10 11 15 1
10 7 1 8

3 100 100
3 5 6
11 11 11
15 32 51

*/
#include <map>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define CLR(c,v) (memset(c,v,sizeof(c)))
using namespace std;

struct G{
	int t,v,c;
	bool operator <(const G &a)const {
		return t < a.t;
	}
}g[200];

int main(){
	freopen("in.txt","r",stdin);
	int n , k, t;
	while(cin >> n >> k >> t){
		CLR(g,0);
		for(int i = 0 ; i < n ; i++)
			scanf("%d",&g[i].t);
		for(int i = 0 ; i < n ; i++)
			scanf("%d",&g[i].v);
		for(int i = 0 ; i < n ; i++)
			scanf("%d",&g[i].c);
		sort(g , g + n);
		int ans = 0;
		for(int i = 0 ; i < n ; i ++){
			int mmax = 0;
			for(int j = 0 ; j < i ; j++){
				if(abs(g[j].c - g[i].c) <= g[i].t - g[j].t){
					mmax = max(g[j].v , mmax);
				}
			}
			g[i].v = ( g[i].c > g[i].t ? 0 : mmax + g[i].v); // 把每

個賊的價值更新爲最大值,如果能達到
			ans = max(ans , g[i].v);
		}
		cout << ans << endl;
	}
	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章