hdoj 2955 robberies 一维01背包

在刚接触这道题的时候,确实无从下手,因为我记得高老师说过01背包算法并不是一个好算法,时间复杂度是指数级。这题容量为实数时,更是无法直接解决。参考了一下别人的思路,发现原来可以把银行总存款作为背包容量,把被抓率转换成逃脱率(即1-被抓率)作为背包物件的价值,进行动态01决策。求出比最低逃脱率大的第一个逃脱率,这时的偷得的存款即为最大可偷的存款。代码如下:

//以总资产为容量,以逃脱率为价值,DP求出第一个比最低逃脱率大的最大偷钱数目
#include <stdio.h>
#define M 100050
#define N 150
double C[M],r[N];//r[N]为逃脱率,w[N]为银行存款,
int W,w[N],n;//W为总存款,n为银行数目

void knapsack()
{
	int i,j;
	for(i=1;i<=W;i++) C[i]=0;
	C[0]=1;
	for(i=1;i<=n;i++)
		for(j=W;j>=1;j--)
		{
			if(j>=w[i]&&C[j-w[i]]*r[i]>C[j])//逃脱率相乘
				C[j]=C[j-w[i]]*r[i];
		}
	return ;
}

int main()
{
	int i,t;
	double rate;//rate为能承受的最低逃脱率
//	freopen("DP.txt","r",stdin);
	scanf("%d",&t);
	while(t--)
	{
		scanf("%lf%d",&rate,&n);
		rate=1-rate;
		for(i=1;i<=n;i++)
			scanf("%d%lf",&w[i],&r[i]),r[i]=1-r[i];
		for(i=1,W=0;i<=n;i++) W+=w[i];
		knapsack();
//		for(i=0;i<=W;i++) printf("%f ",C[i]);
//		printf("\n");
		for(i=W;i>=0;i--)
			if(rate<=C[i]) {printf("%d\n",i);break;}
	}
	return 0;
}
posted @ 2011-08-02 21:03  Veegin  阅读(536)  评论(0编辑  收藏  举报