题目要求:
解题思路:
看到题目想到了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