题目要求:
解题思路:
看到题目想到了0-1背包问题,可以按照这种思路,求出在有限的钱数中找到概率和最大的组合,然后用1减去各个概率的乘积,也就是用1减去这几种情况都没有拿到offer的情况即为至少拿到一个offer。状态转移方程dp[i]=max[dp[i],dp[i-a]+b};
这样做的话,还得需要记录路径。所以想到,可以将状态转移数组初始化为1,然后在循环过程中,直接记录没有拿到offer的概率的乘积。dp[i]=min{dp[i],dp[i-a]*(1-b)}
代码如下:
# include <iostream> # include <algorithm> using namespace std; struct node { <span style="white-space:pre"> </span>int a; <span style="white-space:pre"> </span>double b; }school[10002]; double dp[10001]; int main() { <span style="white-space:pre"> </span>freopen("input.txt","r",stdin); <span style="white-space:pre"> </span>int n,m; <span style="white-space:pre"> </span>while(scanf("%d%d",&n,&m)!=EOF && (n!=0 || m!=0)) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>memset(dp,0,sizeof(dp)); <span style="white-space:pre"> </span>int i,j; <span style="white-space:pre"> </span>for(i=0;i<m;i++) <span style="white-space:pre"> </span>scanf("%d%lf",&school[i].a,&school[i].b); <span style="white-space:pre"> </span>dp[n]=0; <span style="white-space:pre"> </span>for(i=0;i<=n;i++) <span style="white-space:pre"> </span>dp[i]=1; <span style="white-space:pre"> </span>for(i=0;i<m;i++) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>for(j=n;j>=school[i].a;j--) <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>if(dp[j]>dp[j-school[i].a]*(1-school[i].b)) <span style="white-space:pre"> </span>dp[j]=dp[j-school[i].a]*(1-school[i].b); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>printf("%.1lf%%\n",(1-dp[n])*100); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/fyy607/article/details/48001295