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;

}

你可能感兴趣的:(IE)