HDU -- 1203 I NEED A OFFER!

题目简述:Speakless没有多少钱,总共只攒了n万美元。他将在m个学校中选择若干的(当然要在他的经济承受范围内)。每个学校都有不同的申请费用a(万美元),并且Speakless估计了他得到这个学校offer的可能性b。不同学校之间是否得到offer不会互相影响。他可以收到至少一份offer的最大概率。

总体思路:求至少收到一份offer的最大概率,可以反过来求没有收到offer的概率,再用1减去这个概率即得到所求的概率。

细节分析:这是一道01背包题,一开始用二维数组做的,但是内存超了,改为一位数组过了;

用dp[j]表示用j万元申请学校没得到offer的概率,初始化dp[]为1,表示没有得到学校的offer最大概率,接下来再比较dp[j-cost[i]]*p[i](申请学校i没得到offer的概率)与dp[j](不申请学校i没得offer的概率),当然是没有得到offer概率小的好了,所以最终的状态转移方程即为:dp[j]=min(dp[j],dp[j-cost[i]]*p[i]),j>=cost[i];

要注意列举m的时候要按照m递减的顺序来循环。其实这个算法对照着dp的二维数组容易看一些 dp[i][j]=min(dp[i-1][j],dp[i-1][j-cost[i]]*p[i]),让m递减,是为了保证dp[j]是由dp[i-1][j](即一维数组中的dp[j])dp[i-1][j-cost[i]]*p[i](即dp[j-cost[i]]*p[i])递推而来,联想一下滚动数组的优化过程。这也是保证了每个学校只选一次,保证在考虑“选入第i个学校”这个策略时,依据的是绝无已经选入第i个学校的子结果dp[j-cost[i]];(用一维数组自己画一下)

代码实现过程如下:

#include<stdio.h>
const int Max=10010;
float dp[Max],offer[Max];
int cost[Max];
int main(){
    int n,m;
    while(~scanf("%d%d",&m,&n)&&(m+n)){
        for(int i=1;i<=n;i++)
            scanf("%d%f",&cost[i],&offer[i]);
        for(int i=0;i<=m;i++){
                dp[i]=1.0;
        }
        for(int i=1;i<=n;i++){
            for(int j=m;j>=cost[i];j--){
                if(dp[j-cost[i]]*(1-offer[i])<dp[j])
                    dp[j]=dp[j-cost[i]]*(1-offer[i]);
            }
        }
        /*for(int i=0;i<=m;i++)
            printf("%.3f ",dp[i]);
        printf("\n");*/
        float g=(1-dp[m])*100;
        printf("%.1f%%\n",g);
    }
    return 0;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值