HDU4815 Little Tiger vs. Deep Monkey——0-1背包
题目描述
对于n道题目,每道题目有一个分值,答对加分,答错不得分,你要和一个叫深猴的比赛,题目你可以假设成判断题(不是对就是错),深猴对于所有的题目都是随机选择一个答案,而你是有脑子的,求为了不输掉比赛(平局或你获胜)的可能性至少为p时你至少需要得到多少分,有t组数据,每次输入两行,第一行为n,p(有n道题目,n<=40, 不会输的可能性为p,0.0<=p<=1.0),第二行输入n个1~1000的整数,代表这n道题分别答对能获得的分数
样例输入
- 1
- 3 0.5
- 1 2 3
样例输出
- 3
题目分析
首先对于这n道题目,深猴每次不是√就是×,那么答完所有的题目它的分数有2^n个结果(但是这其中可能会重复,比如三道题每题一分1 0 0和0 0 1其实得到的分数是一样的),而对于我们而言,我需要求出这n个题目自己得到每一种可能的分数的可能性,然后按分数从小到大将,这得到这些分数的概率相加,直到有一个分数m时,前面相加的概率和>=p,则在分数大于等于m时,确保我有至少p的概率不会输掉比赛
错误示例
我第一次做这道题目的时候想的通过递归计算出做出n个选择之后我可以得到的每一个分数的种数存放在a数组中,a[i]代表总分为i的种数,而又建立了一个辅助数组b[i]存放分数比i小的种数有多少种,很显然b[i] = b[i-1] + a[i-1](比i小的数量等于比i-1小的数量加上a[i-1]的数量),最后也是从小到大将每一种得分的可能性相加直到大于等于p时的分数则是答案,是一种前缀和的思想,但是会超时
- #include<iostream>
- #include<stdio.h>
- #include<string.h>
- #include<math.h>
- using namespace std;
- int k[];
- int a[];
- int b[];
- int n;
- double p;
- void dfs(int i, int flag, int sum){ //第i个 选or不选 前一个状态的和
- if(i > n){ //只有当所有的n个都作出了选择之后才能算是一种选择方案
- a[sum]++;
- return;
- }
- if(flag == ){ //选
- int next_sum = sum + k[i];
- // a[next_sum]++;
- dfs(i+, , next_sum);
- dfs(i+, , next_sum);
- }else{ //不选
- int next_sum = sum;
- // a[next_sum]++;
- dfs(i+, , next_sum);
- dfs(i+, , next_sum);
- }
- }
- void run(){
- //下一个的下标 选or不选 目前为止的和
- dfs(, , );
- dfs(, , );
- }
- void pre(){
- b[] = ;
- int end = n*;
- for(int i = ; i <= end; i++){ //b[i]存放比i小的取法的数量
- b[i] = b[i-] + a[i-];
- }
- }
- void judge(){
- double m = ;
- for(int i = ; i <= n; i++){
- m *= ;
- }
- m *= p;
- long long x = ceil(m);
- int ans;
- int end = n*;
- for(int i = ; i <= end; i++){
- if(b[i] >= x){
- ans = i;
- break;
- }
- }
- printf("%d\n", ans);
- }
- int main(){
- int t;
- scanf("%d", &t);
- while(t--){
- scanf("%d%lf", &n, &p);
- memset(a, , sizeof(a));
- memset(b, , sizeof(b));
- for(int i = ; i <= n; i++) scanf("%d", &k[i]);
- run();
- pre();
- judge();
- }
- return ;
- }
正确思路
本题可以用到动态规划,0-1背包的思想,a[i]存放这n个题目的分数,dp[i][j]存放前i题,得到j分数的种数,而我们很显然可以想到,对于分数j,如果dp[i][j]可以得到,则他一定是dp[i-1][j-a[i]](第i题的分数取的种数) + dp[i-1][j](第i题的分数不取的种数)的基础上来的(对于第i题而言取的话,j == j - a[i] + a[i],不取的话就是i-1个问题,分数为j的种数,是0-1背包的问题),所以我们也可以对此用一个一维数组进行优化,dp[x]存放分数为x的种数,而初始化时dp[0] == 1,因为可以理解成前0题,得到0分的种数为1
正确代码
- #include<iostream>
- #include<stdio.h>
- #include<math.h>
- #include<string.h>
- using namespace std;
- const int N = ;
- int a[];
- double dp[N];
- int n;
- double p;
- int main(){
- int t;
- scanf("%d", &t);
- while(t--){
- scanf("%d%lf", &n, &p);
- int sum = ;
- for(int i = ;i <= n; i++){ //sum统计最大可以得到的分数
- scanf("%d", &a[i]);
- sum += a[i];
- }
- memset(dp, , sizeof(dp));
- dp[] = ; //前0题,得到0分的次数位1
- for(int i = ; i <= n; i++){ //类似于0-1背包的两个循环
- for(int j = sum; j >= a[i]; j--){
- dp[j] += dp[j-a[i]]; //核心步骤,对于dp[j]而言,得分为j的种数是前i-1个时得分为j-a[i] 也就是取第i题,加上前i-1个时得分为j的种数 也就是不取第i题
- }
- }
- double m = pow(,n); //统计所有的深猴的得分个数
- int ans = ;
- double ssum = ;
- for(int i = ; i <= sum; i++){
- dp[i] /= m; //从小到大将概率累加直到大于等于p时的分数i就是答案,注意0也是一个得分
- ssum += dp[i];
- if(ssum >= p){
- ans = i;
- break;
- }
- }
- printf("%d\n", ans);
- }
- return ;
- }
HDU4815 Little Tiger vs. Deep Monkey——0-1背包的更多相关文章
- hdu 4815 Little Tiger vs. Deep Monkey(01背包)
http://acm.hdu.edu.cn/showproblem.php?pid=4815 Description A crowd of little animals is visiting a m ...
- hdu 4815 Little Tiger vs. Deep Monkey
概率dp,有点像背包的做法: dp[i][j]代表前i个数组成的j数的概率为多少 #include<cstdio> #include<cstring> #define maxn ...
- HDU - 4815 Little Tiger vs. Deep Monkey (长春赛区C题)
题意:有A,B两个人.n道题目.每题有相应的分数.B答对题目的概率是0.5.求A不输给B的概率不小于P要拿的最低分数 思路:DP,dp[i][j]来表示B答了前i题后分数为j的概率,,然后通过B的概率 ...
- HDU 4815 Little Tiger vs. Deep Monkey(2013长春现场赛C题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4815 简单的DP题. #include <stdio.h> #include <st ...
- HDU 4815 Little Tiger vs. Deep Monkey 2013 长春现场赛C题
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4815 [题意] n个题目,每题有各自的分数,A有50%的概率答对一道题目得到相应分数,B想要在至少P的概率 ...
- poj1417 带权并查集+0/1背包
题意:有一个岛上住着一些神和魔,并且已知神和魔的数量,现在已知神总是说真话,魔总是说假话,有 n 个询问,问某个神或魔(身份未知),问题是问某个是神还是魔,根据他们的回答,问是否能够确定哪些是神哪些是 ...
- P1417 烹调方案 (0/1背包+贪心)
题目背景 由于你的帮助,火星只遭受了最小的损失.但gw懒得重建家园了,就造了一艘飞船飞向遥远的earth星.不过飞船飞到一半,gw发现了一个很严重的问题:肚子饿了~ gw还是会做饭的,于是拿出了储藏的 ...
- 洛谷 P1064 金明的预算方案 (有依赖的0/1背包)
题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间.更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过NN元钱就行”. ...
- POJ 1636 Prison rearrangement DFS+0/1背包
题目链接: id=1636">POJ 1636 Prison rearrangement Prison rearrangement Time Limit: 3000MS Memor ...
随机推荐
- python3.5.3rc1学习四:类
class calculator: def add(x,y): return x + y print(added) def sub(x,y): return x - y print(sub) def ...
- java中的字符串二
public class TestString { public static void main(String[] args) { // TODO Auto-generated method stu ...
- cookiecutter
1.安装cookiecutter pip3 install cookiecutter 2.设置模板 https://github.com/cookiecutter/cookiecutter 搜索需 ...
- Ultimate Chicken Horse GameProject第三次迭代成果文档
经过三次迭代我们实现了游戏的基本功能 项目文档的github链接:https://github.com/k6tok12355/Ultimate-Chicken-Horse 下面是我们在第一次迭代中设定 ...
- CF-weekly4 D. Haar Features
https://codeforces.com/gym/253910/problem/D D. Haar Features time limit per test 1 second memory lim ...
- Token认证,如何快速方便获取用户信息
背景 我们有一个Web项目,这个项目提供了很多的Rest API.也做了权限控制,访问API的请求必须要带上事先认证后获取的Token才可以. 认证的话就在Filter中进行的,会获取请求的Token ...
- WIFI Portal登录
开头 关于 ANDROID 5.0-7.1.2 网络图标上的感叹号及其解决办法-狐狸的小小窝 HTTP状态码之204 No Content 原理 访问generate_204地址,如果得到状态码是20 ...
- 物联网架构成长之路(37)-基于C#开发串口工具
0. 前言 作为物联网平台开发,最基础的工具链还是要有的.前几篇博客,介绍了用C#开发一个MQTT的客户端,用于模拟设备连接平台,并发送数据到平台.但是对于一些硬件来说,可能会用到串口uart来发送数 ...
- mybatis的参数传递
mybatis的参数传递分为两种:1.单参数传递 2.多参数传递 单参数 mybatis会直接取出参数值给Mapper文件赋值 例子如下: 1.Mapper文件内容如下: public void d ...
- Java的POJO和JavaBean的区别
POJO Plain Ordinary Java Object,即简单的java对象. 特点 需要有一些 private 的参数,以及针对参数的 setter 和 getter 方法来访问这些参数. ...