题意:
Harry Potter 抢银行?每个银行有 m[i] millions ,同时又有 p[i]的概率被抓
在给定的p下,要求被抓概率小于p最多能抢多少钱?
把银行看出石头,价值看成容量,概率看成价值 做01背包
从这里可以看出转移方程:0.02 + (1 - 0.02) * .03 = 0.0494
dp[i]=dp[i-a] + ( 1 - dp[i-a] )*p
#include<stdio.h>
#include<algorithm>
using namespace std;
int m[110];
double pi[110];
double dp[110][10010];
int main()
{
int t,k=1;
double p;
int n,sum,ans;
scanf("%d",&t);
while(t--)
{
sum=0;
ans=0;
scanf("%lf %d",&p,&n);
for(int i=1;i<=n;i++){
scanf("%d %lf",m+i,pi+i);
sum+=m[i];
}
for(int i=1;i<=sum;i++) dp[0][i]=-1.0;
dp[0][0]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=sum;j++)
{
if(j<m[i]|| dp[i-1][j-m[i]] <0) dp[i][j]=dp[i-1][j];
else if(dp[i-1][j]<0.0) dp[i][j]=dp[i-1][j-m[i]]+(1-dp[i-1][j-m[i]])*pi[i];
else dp[i][j]=min(dp[i-1][j],dp[i-1][j-m[i]]+(1-dp[i-1][j-m[i]])*pi[i]);
}//转移方程
for(int i=sum;i>=0;i--)
if(dp[n][i]<=p&&dp[n][i]>=0){
ans=i;
break;
}
printf("Case %d: %d\n",k++,ans);
}
return 0;
}
逆着做,求最小的被抓概率就是最大的不被抓概率
这样写更简单方便
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int m[110];
double pi[110];
double dp[10010];
int main()
{
int t,k=1;
double p;
int n,sum,ans;
scanf("%d",&t);
while(t--)
{
sum=0;
ans=0;
scanf("%lf %d",&p,&n);
p=1-p;
for(int i=1;i<=n;i++){
scanf("%d %lf",m+i,pi+i);
pi[i]=1-pi[i];
sum+=m[i];
}
memset(dp,0,sizeof(dp));
dp[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=sum;j>=m[i];j--){
dp[j]=max(dp[j],dp[j-m[i]]*pi[i]); //转移方程
}
}
for(int i=sum;i>=0;i--)
if(dp[i]>=p){
printf("Case %d: %d\n",k++,i);
break;
}
}
return 0;
}