1. 程式人生 > >HDU2955Robberies (0-1揹包問題)

HDU2955Robberies (0-1揹包問題)

題目大意:

       一個人要搶劫銀行,在保證被抓概率小於某個預設的概率值時,儘可能搶到更多的錢。

輸入:第一行是一個整數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;
}