7655: 寵物小精靈之收服 二維費用揹包問題
描述
寵物小精靈是一部講述小智和他的搭檔皮卡丘一起冒險的故事。
一天,小智和皮卡丘來到了小精靈狩獵場,裡面有很多珍貴的野生寵物小精靈。小智也想收服其中的一些小精靈。然而,野生的小精靈並不那麼容易被收服。對於每一個野生小精靈而言,小智可能需要使用很多個精靈球才能收服它,而在收服過程中,野生小精靈也會對皮卡丘造成一定的傷害(從而減少皮卡丘的體力)。當皮卡丘的體力小於等於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
太奇葩了,這道題就是二維費用揹包,但是:皮卡丘體力小於等於0的野生小精靈也不會被小智收服,所以我們迴圈皮卡丘體力的時候應該是不能直接取到第i個怪物的攻擊力的
#include<bits/stdc++.h> using namespace std; long long int dp[1005][1005]; int n,m,k; long long int a[105],b[105]; intmain() { cin>>n>>m>>k; for(int i=1;i<=k;i++)cin>>a[i]>>b[i]; int h = m; for(int i=1;i<=k;i++)//k個怪物 { for(int j=n;j>=a[i];j--) //精靈球 { for(int l=m;l>b[i];l--) //體力 { if(dp[j-a[i]][l-b[i]]+1>dp[j][l]) { dp[j][l] = dp[j-a[i]][l-b[i]]+1; } } } } cout<<dp[n][m]<<" "; while(dp[n][h]==dp[n][m]&&h>=1)h--; cout<<m-h; return 0; }