第九章 動態規劃-1292:寵物小精靈之收服

1292:寵物小精靈之收服

時間限制: 1000 ms 內存限制: 65536 KB
提交數: 3074 通過數: 1884
【題目描述】
寵物小精靈是一部講述小智和他的搭檔皮卡丘一起冒險的故事。

一天,小智和皮卡丘來到了小精靈狩獵場,裏面有很多珍貴的野生寵物小精靈。小智也想收服其中的一些小精靈。然而,野生的小精靈並不那麼容易被收服。對於每一個野生小精靈而言,小智可能需要使用很多個精靈球才能收服它,而在收服過程中,野生小精靈也會對皮卡丘造成一定的傷害(從而減少皮卡丘的體力)。當皮卡丘的體力小於等於0時,小智就必須結束狩獵(因爲他需要給皮卡丘療傷),而使得皮卡丘體力小於等於0的野生小精靈也不會被小智收服。當小智的精靈球用完時,狩獵也宣告結束。

我們假設小智遇到野生小精靈時有兩個選擇:收服它,或者離開它。如果小智選擇了收服,那麼一定會扔出能夠收服該小精靈的精靈球,而皮卡丘也一定會受到相應的傷害;如果選擇離開它,那麼小智不會損失精靈球,皮卡丘也不會損失體力。

小智的目標有兩個:主要目標是收服儘可能多的野生小精靈;如果可以收服的小精靈數量一樣,小智希望皮卡丘受到的傷害越小(剩餘體力越大),因爲他們還要繼續冒險。

現在已知小智的精靈球數量和皮卡丘的初始體力,已知每一個小精靈需要的用於收服的精靈球數目和它在被收服過程中會對皮卡丘造成的傷害數目。請問,小智該如何選擇收服哪些小精靈以達到他的目標呢?

【輸入】
輸入數據的第一行包含三個整數:N(0<N<1000),M(0<M<500),K(0<K<100),分別代表小智的精靈球數量、皮卡丘初始的體力值、野生小精靈的數量。

之後的K行,每一行代表一個野生小精靈,包括兩個整數:收服該小精靈需要的精靈球的數量,以及收服過程中對皮卡丘造成的傷害。

【輸出】
輸出爲一行,包含兩個整數:C,R,分別表示最多收服C個小精靈,以及收服C個小精靈時皮卡丘的剩餘體力值最多爲R。

【輸入樣例】
10 100 5
7 10
2 40
2 50
1 20
4 20
【輸出樣例】
3 30
【提示】
樣例輸入2:

10 100 5

8 110

12 10

20 10

5 200

1 110

樣例輸出2:

0 100

提示:

對於樣例輸入1:小智選擇:(7,10) (2,40) (1,20) 這樣小智一共收服了3個小精靈,皮卡丘受到了70點傷害,剩餘100-70=30點體力。所以輸出3 30。

對於樣例輸入2:小智一個小精靈都沒法收服,皮卡丘也不會收到任何傷害,所以輸出0 100。


思路:數組需開大點,避免爆掉。這個是典型的二維揹包問題,套用二維揹包的模板(即0-1揹包加上一層for循環),最後要求的是剩餘體力的最大值,所以最後的for循環是爲了找到和收付精靈數量一致的情況下,消耗體力最小值,用m - ans即爲所求剩餘最大值。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 5000
using namespace std;
int f[N][N];
int n,m,k;
int a[N],b[N],c[N];
int main(){
	cin >> n >> m >> k;
	for(int i = 1; i <= k; i++)
	cin >> a[i] >> b[i];
	for(int i = 1; i <= k ;i++)//判斷是離開還是收復效益更大
	{
		for(int j = n; j >= a[i];j--){
			for(int l = m ; l >= b[i];l--)
			f[j][l] = max(f[j][l],f[j-a[i]][l-b[i]]+1);
		}
	 } 
	int ans;
	for(ans = 0; ans <= m; ans++)
	if(f[n][ans] == f[n][m]) break;
	printf("%d %d\n",f[n][m],m - ans);//f[n][m]收復精靈最大數,m-ans 剩餘體力
	return 0;
}

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