HDOJ.2955 Robberies (01背包+概率问题)
Robberies
算法学习—–动态规划初探
题意分析
有一个小偷去抢劫银行,给出来银行的个数n,和一个概率p为能够逃跑的临界概率,接下来有n行分别是这个银行所有拥有的钱数mi和抢劫后被抓的概率pi,求在不被抓的情况下,小偷能抢到的最多的钱是多少。
显然这是一道概率问题,计算小偷不能逃的概率是不好算的,不如计算他成功的概率。若把题目中每个数据变成能够逃跑的概率,那就是1-pi。
我们先举个简单的例子.
不妨假设有3个银行:
①如果小偷都能抢劫,那么抢劫后能逃跑的概率就是(1-p1) * (1-p2) * (1-p3),对应抢到的金钱就是m1+m2+m3
②若他只能抢劫其中2个,那么就是有下面3种情况
| ~ | case1 | case 2 | case3 |
|---|---|---|---|
| 成功概率 | (1-p1) * (1-p2) | (1-p1) * (1-p3) | (1-p2) * (1-p3) |
| 获得金钱 | m1+m2 | m1+m3 | m2+m3 |
③若他只能抢劫1个,那么他只有3中选择
④或者他一个都抢劫不了,那……
好了到这里就差不多理解题目的大意了。因为在概率里面,2件独立事情一起发生的概率是每个事件发生概率的乘积。(如果表述有不合理的地方,请各位留言指正)
我们接着看小偷,小偷面对每个银行,有偷或者不偷2种选择,这不就是典型的0/1背包问题的情景吗?那么限制小偷的偷东西的是什么呢?显然是他被抓的概率,同时小偷想获得最大价值的金钱,不妨我们做个对比:
背包容量(限制拿东西)-> 被抓概率(限制偷东西)
商品价值(希望最大) -> 金钱数量(希望最大)
到这里,大概就能看出来了,dp数组应该保存的是概率(开double类型),数组的下标代表所偷到的金钱。
下面仍有几点需要注意的(个人意见,仅供参考):
1.dp[0]要初始化为1,也很容易理解,啥都没有偷,被抓的概率为0,成功概率为100%;
2.dp完之后,应该由大到小遍历一遍,一旦有一种情况的成功概率大于等于(1-p) p为每组数据一开始给出来的那个临界,输出对应的金钱,break即可。
代码总览
/*
Title:HDOJ.2955
Auhtor:pengwill
Date:2016-12-18
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define ma 105
using namespace std;
int m[ma];
double dp[10000],p[ma];
int main()
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--){
int n,i,j,sum = 0;double pmax;
scanf("%lf %d",&pmax,&n);
pmax = 1-pmax;
memset(m,0,sizeof(m));
memset(p,0,sizeof(p));
for(i = 1;i<=n;++i){
scanf("%d %lf",&m[i],&p[i]);
sum+=m[i];
p[i] = 1-p[i];
}
memset(dp,0,sizeof(dp));
dp[0] =1;
for(j = 1;j<=n;++j)
for(i = sum;i>=m[j];--i)
dp[i] = max(dp[i],dp[i-m[j]]*p[j]);
for(i = sum;i>=0;--i)
if(dp[i]>=pmax)
break;
printf("%d\n",i);
}
return 0;
}
HDOJ.2955 Robberies (01背包+概率问题)的更多相关文章
- HDOJ 2955 Robberies (01背包)
10397780 2014-03-26 00:13:51 Accepted 2955 46MS 480K 676 B C++ 泽泽 http://acm.hdu.edu.cn/showproblem. ...
- hdu 2955 Robberies 0-1背包/概率初始化
/*Robberies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- hdu 2955 Robberies (01背包)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2955 思路:一开始看急了,以为概率是直接相加的,wa了无数发,这道题目给的是被抓的概率,我们应该先求出总的 ...
- HDU 2955 Robberies(01背包变形)
Robberies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- hdu 2955 Robberies (01背包好题)
Robberies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- HDU——2955 Robberies (0-1背包)
题意:有N个银行,每抢一个银行,可以获得\(v_i\)的前,但是会有\(p_i\)的概率被抓.现在要把被抓概率控制在\(P\)之下,求最多能抢到多少钱. 分析:0-1背包的变形,把重量变成了概率,因为 ...
- HDU 2955 Robberies --01背包变形
这题有些巧妙,看了别人的题解才知道做的. 因为按常规思路的话,背包容量为浮点数,,不好存储,且不能直接相加,所以换一种思路,将背包容量与价值互换,即令各银行总值为背包容量,逃跑概率(1-P)为价值,即 ...
- HDU 2955 Robberies(01背包)
Robberies Problem Description The aspiring Roy the Robber has seen a lot of American movies, and kno ...
- Robberies(HDU2955):01背包+概率转换问题(思维转换)
Robberies HDU2955 因为题目涉及求浮点数的计算:则不能从正面使用01背包求解... 为了能够使用01背包!从唯一的整数(抢到的钱下手)... 之后就是概率的问题: 题目只是给出被抓的 ...
随机推荐
- 「日常训练」Equation(HDU-5937)
题意与分析 时隔一个月之后来补题.说写掉的肯定会写掉. 题意是这样的:给1~9这些数字,每个数字有\(X_i\)个,问总共能凑成多少个不同的等式\(A+B=C\)(\(A,B,C\)均为1位,\(1+ ...
- 结合BeautifulSoup和hackhttp的爬虫实例
网页页数的改变 headers头不添加
- 记录---Testin上新手测试用例设计实战---碎乐3.2.0
平台上给的版本是碎乐3.12版的,但是平台上给的安装包下载不了,所以加群咨询之后给出了直接去手机应用商店下载搜索到的版本的对策.所以就那应用商店中找到的3.2.0版本来设计测试用例.因为任务中没有给出 ...
- 通过 Python_Faker 生成测试数据
通过 Python_Faker 生成测试数据 一.介绍 在软件需求.开发.测试过程中,有时候需要使用一些测试数据,针对这种情况,我们一般要么使用已有的系统数据,你不可能通过手工来生成(最傻的方法)可能 ...
- linux部署MantisBT(三)部署MantisBT
三.部署MantisBT 1.下载MantisBT https://www.mantisbt.org/download.php 2.将MantisBT安装包放在/apache/htdocs下并重命名为 ...
- oracle 学习随笔一: 字段大小写
字段上加大小写:"reportId" 即可
- Python入门(5)
导览: 函数 集合 迭代器与生成器 模块 一.函数 只要学过其他编程语言应该对函数不太陌生,函数在面向过程的编程语言中占据了极重要的地位,可以说没有函数,就没有面向过程编程,而在面向对象语言中,对象的 ...
- Python实现个性化推荐二
基于内容的推荐引擎是怎么工作的 基于内容的推荐系统,正如你的朋友和同事预期的那样,会考虑商品的实际属性,比如商品描述,商品名,价格等等.如果你以前从没接触过推荐系统,然后现在有人拿枪指着你的头,强迫你 ...
- Docker学习笔记总结
Docker学习笔记 https://yeasy.gitbooks.io/docker_practice/content/ 一 环境搭建 Ubuntu安装 .添加软件源的GPG密钥 curl -f ...
- sqoop-1.4.6安装与使用
一.安装 1.下载sqoop-1.4.6-bin.tar.gz并解压 2.修改conf/sqoop-env.sh,设置如下变量: export HADOOP_COMMON_HOME=/usr/loca ...