HDU2955Robberies (0-1揹包問題)
阿新 • • 發佈:2019-01-10
題目大意:
一個人要搶劫銀行,在保證被抓概率小於某個預設的概率值時,儘可能搶到更多的錢。
輸入:第一行是一個整數t,代表測試用例的個數
接下來第一行是一個小數P和一個整數N,N代表銀行的個數,P代表概率的上限。
接下來N行,每行兩個數,第一個整數代表該銀行的錢數,第二個小數代表被抓的概率。
輸出:輸出每種情況能得到的最大的錢數。
解題思路:
典型的0-1揹包問題,但剛聯絡揹包問題不久,剛看到題目按照正常的0-1揹包問題去考慮,發覺揹包的空間是小數,沒有辦法進行,考慮換種思路。
將N個銀行的總錢數看做是被揹包空間,每個銀行的錢數看成是重量,搶劫每個銀行不被抓的概率為價值,因而得到狀態轉移方程如下:
dp[j]=max(dp[j],dp[j-bank[i].money]*(1-bank[i].p));(其中dp[j]表示搶劫得到的錢數為j時不被抓的概率。
程式碼如下:
# include <iostream> # include <algorithm> using namespace std; struct node { int money; double p; }bank[10002]; double max(double a,double b) { if(a>=b) return a; else return b; } double dp[10002]; int main() { freopen("input.txt","r",stdin); int t; scanf("%d",&t); while(t--) { double posibility; int n; scanf("%lf %d",&posibility,&n); int i,j,money; money=0; for(i=0;i<n;i++) { scanf("%d %lf",&bank[i].money,&bank[i].p); money+=bank[i].money; } memset(dp,0,sizeof(dp)); dp[0]=1; for(i=0;i<n;i++) { for(j=money;j>=bank[i].money;j--) { dp[j]=max(dp[j],dp[j-bank[i].money]*(1-bank[i].p)); } } for(i=money;i>=0;i--) if(dp[i]>=(1-posibility)) { printf("%d\n",i); break; } } return 0; }