2008 APAC local onsites C Millionaire (动态规划,离散化思想)
Problem
You have been invited to the popular TV show "Would you like to be a millionaire?". Of course you would!
The rules of the show are simple:
Before the game starts, the host spins a wheel of fortune to determine P, the probability of winning each bet.
You start out with some money: X dollars.
There are M rounds of betting. In each round, you can bet any part of your current money, including none of it or all of it. The amount is not limited to whole dollars or whole cents.
If you win the bet, your total amount of money increases by the amount you bet. Otherwise, your amount of money decreases by the amount you bet.
After all the rounds of betting are done, you get to keep your winnings (this time the amount is rounded down to whole dollars) only if you have accumulated $1000000 or more. Otherwise you get nothing.
Given M, P and X, determine your probability of winning at least $1000000 if you play optimally (i.e. you play so that you maximize your chances of becoming a millionaire).
Input
The first line of input gives the number of cases, N.
Each of the following N lines has the format "M P X", where:
M is an integer, the number of rounds of betting.
P is a real number, the probability of winning each round.
X is an integer, the starting number of dollars.
Output
For each test case, output one line containing "Case #X: Y", where:
X is the test case number, beginning at 1.
Y is the probability of becoming a millionaire, between 0 and 1.
Answers with a relative or absolute error of at most 10-6 will be considered correct.
Limits
1 ≤ N ≤ 100
0 ≤ P ≤ 1.0, there will be at most 6 digits after the decimal point.
1 ≤ X ≤ 1000000
Small dataset
1 ≤ M ≤ 5
Large dataset
1 ≤ M ≤ 15
Sample

In the first case, the only way to reach $1000000 is to bet everything in the single round.
In the second case, you can play so that you can still reach $1000000 even if you lose a bet. Here's one way to do it:
You have $600000 on the first round. Bet $150000.
If you lose the first round, you have $450000 left. Bet $100000.
If you lose the first round and win the second round, you have $550000 left. Bet $450000.
If you win the first round, you have $750000 left. Bet $250000.
If you win the first round and lose the second round, you have $500000 left. Bet $500000.
题意:
最开始你有x元钱,要进行M轮赌博。每一轮赢的概率为P,你可以选择赌与不赌,如果赌也可以将所持的任意一部分钱作为赌注(可以是整数,也可以是小数)。如果赢了,赌注将翻倍;输了赌注则没了。在M轮赌博结束后,如果你持有的钱在100万元以上,就可以把这些钱带回家。问:当你采取最优策略时,获得100万元以上的钱并带回家的概率是多少。
分析:
由于每一轮的赌注是任意的,不一定为整数,因而有无限种可能,所以即便想穷竭搜索也无从着手。但如果能化连续为离散,那么可能便也是有限的了。具体如下:假设前M-1轮的赌博后,还持有x'元。对于最后一轮,考虑的情况有3种。如果x' >= 100万,则没有必要再赌了即最后一轮赢的概率为0;如果50<= x' < 100万,只要参与赌博并且赌注 >= 50万则有赢的概率为P;如果x' < 50万,那么无论是否参与最后一轮的赌博,压的赌注是多少赢的概率必为0。我们不妨看一下倒数第二轮与最后一轮的关系,设在倒数第二轮时持有的钱为x。如果x >= 100万,赢的概率为1;如果x < 25万,即便最后两轮赌博都赢了总钱数必小于100万,所以赢的概率为0;否则,只要选择参与至少一轮赌博并且赌注至少25万则有赢得概率。假设倒数第二轮的赌注为y(y = 0 或 y >= 25万),则最后一轮持有的钱x' = (x + y)或x' = (x - y)。而倒数第二轮考虑的情况具体可以分为5种。综上,当参与M轮赌博时所需考虑的情况总共有2^m + 1种,可以通过dp解决。定义一个二维dp数组,dp[i][j] := 参与第i轮赌博,持有的钱所在模块为j并且采取最优策略时赢的概率。初始化:dp[n][1 << m] = 1,状态转移方程dp[i][j] = max(P * dp[i + 1][j + k] + (1 - P) * dp[i + 1][j - k] / 0 <= k <= min(j, n - j) )。时间复杂度O(m*2^2m)。
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
typedef long long int LL;
int M , X ;
double P;
double dp[2][(1 << 15) + 1];
void solve()
{
int n = 1 << M;
double *pre = dp[0] , *nxt = dp[1];
memset(pre , 0 , sizeof(double) * (n + 1));
///memset(pre , 0 , sizeof(pre)); 这样初始化是不行的,因为pre为一个double型的指针,不是整个数组。
pre[n] = 1.0;///因:模块n对应的资金>= 100万
for(int r = 0 ; r < M; r++)///枚举第几轮
{
for(int i = 0 ; i <= n ; i++)///枚举当前是哪种状态
{
int step = min(i , n - i);///如果step大于n / 2 , 等会儿转移的时候可能会超过n
double t = 0.0;
for(int j = 0 ; j <= step ; j++)///枚举当前的所有可能走法
{
t = max(t , P * pre[i + j] + (1 - P) * pre[i - j]);///求出期望的最大值
}
nxt[i] = t;
}
swap(pre , nxt);///交换两个数组的值进行滚动
}
int i = (LL)X * n / 1000000;///找到X对应的是第几块
// for(int i = 0 ; i <= n ; i++)cout << '*' << pre[i] << endl;
printf("%.6lf\n" , pre[i]);
}
int main()
{
cin >> M >> P >> X;
solve();
return 0;
}
2008 APAC local onsites C Millionaire (动态规划,离散化思想)的更多相关文章
- GCJ 2008 APAC local onsites C Millionaire
时间复杂度很大.dp[i][j]表示第i轮 j这种状态的概率. #include<cstdio> #include<cstring> #include<cmath> ...
- GCJ2008 APAC local onsites C Millionaire
自己Blog的第一篇文章,嗯... 接触这道题,是从<挑战程序设计竞赛>这本书看来的,其实头一遍读题解,并没有懂.当然现在已经理解了,想想当初可能是因为考虑两轮的那张概率图的问题.于是决定 ...
- Code Jam 2008 APAC local onsites Problem C. Millionaire —— 概率DP
题意: 你有X元钱,进行M轮赌博游戏.每一轮可以将所持的任意一部分钱作为赌注(赌注为0元表示这一轮不押),赌注可以是小数的,不是一定要整数.每一轮 赢的概率为P,赢了赌注翻倍,输了赌注就没了.如果你最 ...
- UVA 221 城市化地图(离散化思想)
题意: 给出若干个栋楼俯视图的坐标和面积,求从俯视图的南面(可以视为正视图)看过去到底能看到多少栋楼. 输入第一个n说明有n栋楼,然后输入5个实数(注意是实数),分别是楼的左下角坐标(x,y), 然后 ...
- HDU5124:lines(线段树+离散化)或(离散化思想)
http://acm.hdu.edu.cn/showproblem.php?pid=5124 Problem Description John has several lines. The lines ...
- NOIP 2008 传纸条(洛谷P1006,动态规划递推,滚动数组)
题目链接:P1006 传纸条 PS:伤心,又想不出来,看了大神的题解 AC代码: #include<bits/stdc++.h> #define ll long long using na ...
- USACO 2008 Mar Silver 3.River Crossing 动态规划水题
Code: #include<cstring> #include<algorithm> #include<cstdio> using namespace std; ...
- 此坑待填 离散化思想和凸包 UVA - 10173 Smallest Bounding Rectangle
Smallest Bounding Rectangle Given the Cartesian coordinates of n(>0)2-dimensional points, write a ...
- 算法:贪心、回溯(su)、分治、动态规划,思想简要
贪心算法: 只做出当前看来最好的选择,而不从整体考虑最优,他所作出的是局部最优解.使用该算法的前提是必须具备无后效性,即某个状态以前的选择不会影响以后的状态的选择,只与当前状态有关. 回溯算法: 本质 ...
随机推荐
- 往Matlab中添加工具包
使用Matlab过程中,常常会缺少一些函数包导致无法运行,会显示未定义函数. 假如我要用sigshift( ) 这个移位函数,但Matlab中没有,就会提示错误:未定义函数或变量 'sigshift' ...
- 3ds Max学习日记(六)
到了周六就不想再忙实验室的活了,于是玩了一下3ds max,第5和第6章每章都只有4个视频,于是就一起弄完了,什么网格建模,曲面建模啥的,nurbs啥的. 附上今日的劳动成果: 叉子(用长方体 ...
- cacti监控多个mysql端口
1. 在Console -> Data Templates 找到mysql-cacti-templates的mysql模板,编辑: 在这里面把Port的Use Per-Data Source V ...
- prototype的本质
在<关于思维方式的思绪>那篇文章里提到了, 原型的本质就是一种委托关系. 即我这里没有,就到我的原型里去看看,一旦找到就当成我的用. 本文详细说一下这个事情. 比如某女买东西,钱都是她老公 ...
- vdbench和fio测试磁盘性能的对比总结
一.安装 1.安装vdbench,首先安装java:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-213 ...
- P1667 数列
题目描述 给定一个长度是n的数列A,我们称一个数列是完美的,当且仅当对于其任意连续子序列的和都是正的.现在你有一个操作可以改变数列,选择一个区间[X,Y]满足Ax +Ax+1 +…+ AY<0, ...
- Codeforces Round #469 (Div. 2) F. Curfew
贪心 题目大意,有2个宿管分别从1和n开始检查房间,记录人数不为n的房间个数,然后锁住房间. 没有被锁的房间中的学生可以选择藏在床底,留在原地,或者转移(最远转移d个房间) 然后抄了网上大神的代码 ...
- poj3207 Ikki's Story IV - Panda's Trick 2-sat问题
---题面--- 题意:给定一个圈,m条边(给定),边可以通过外面连,也可以通过里面连,问连完这m条边后,是否可以做到边两两不相交 题解: 将连里面和连外面分别当做一种决策(即每条边都是决策点), 如 ...
- BZOJ4311:向量——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4311 你要维护一个向量集合,支持以下操作: 1.插入一个向量(x,y) 2.删除插入的第i个向量 ...
- openjudge666:放苹果—题解
(测试这里的markdown,同时也有纪念意义吧--第一次写的题解) 当时刚学递推的时候做的一道题 oj上的666题 666:放苹果 总时间限制: 1000ms 内存限制: 65536kB 描述 把M ...