Description

This is back in the Wild West where everybody is fighting everybody. In particular, there are n cowboys, each with a revolver. These are rather civilized cowboys, so they have decided to take turns firing their guns until only one is left standing. Each of them has a given probability of hitting his target, and they all know each other’s probability. Furthermore, they are geniuses and always know which person to aim at in order to maximize their winning chance, so they are indeed peculiar cowboys. If there are several equally good targets, one of those will be chosen at random. Note that a cowboy’s code of ethics forces him to do his best at killing one of his opponents, even if intentionally missing would have increased his odds (yes, this can happen!)

Input

On the first line of the input is a single positive integer t, telling the number of test cases to follow. Each case consists of one line with an integer 2 ≤ n ≤ 13 giving the number of cowboys, followed by n positive integers giving hit percentages for the cowboys in the order of their turns.

Output

For each test case, output one line with the percent probabilities for each of them surviving, in the same order as the input. The numbers should be separated by a space and be correctly rounded to two decimal places.

题目大意:n个枪手,均有一个命中率,从第一位开始,每次下一位开枪射击一个人。问每个人的生存率是多少,枪手总会朝着对自己最有利的人开枪,但一定要开枪,不能向自己开枪,如果有多个最有利的人,随机向其中一个开枪。

思路:O(n^4*2^n)水过去的……所以思路就不怎么讲了……(next每次算会TLE,先预处理出来依然TLE……)现在实在想不到什么好方法先这样吧……

PS:贴一下做题时候的草稿

b[i]为i命中的胜率
a[i]为i不命中的胜率
p[i]为i的命中率
q[i]为1-p[i]
a[i] = p[i+1] * b[i+1] + q[i+1] * a[i+1]
= p[i+1] * b[i+1] + q[i+1] * (p[i+2] * b[i+2] + q[i+2] * a[i+2])
= p[i+1] * b[i+1] + q[i+1] * p[i+2] * b[i+2] + q[i+1] * q[i+2] * a[i+2]
= p[i+1] * b[i+1] + q[i+1] * p[i+2] * b[i+2] + ……
+ pro{q[i+1] .. q[i-1]} * p[i] * b[i] + pro{q[i+1] .. q[i]} * a[i]
a[i] = (p[i+1] * b[i+1] + q[i+1] * p[i+2] * b[i+2] + ……
+ pro{q[i+1] .. q[i-1]} * p[i] * b[i]) / (1 - pro{q[i+1] .. q[i]})

代码(2641MS):

 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL; const int MAXN = ;
const double EPS = 1e-; int T, n;
double dp[MAXN][( << MAXN) + ][MAXN];
double p[MAXN]; inline int sgn(double x) {
return (x > EPS) - (x < -EPS);
} int Tnext[ << MAXN][MAXN]; inline int next(int state, int x) {
if(Tnext[state][x] != -) return Tnext[state][x];
int ret = x;
while(true) {
if(++ret == n) ret = ;
if(state & ( << ret)) break;
}
return Tnext[state][x] = ret;
} inline int count(int state) {
int ret = ;
while(state) {
ret += state & ;
state >>= ;
}
return ret;
} int c[MAXN][MAXN];
double b[MAXN][MAXN], maxb[MAXN]; void dfs(int state, int cur) {
if(dp[cur][state][] != -) return ;
if(count(state) == ) {
for(int i = ; i < n; ++i) dp[cur][state][i] = (i == cur);
return ;
} for(int i = ; i < n; ++i) {
if((state & ( << i)) == ) continue;
for(int tar = next(state, i); tar != i; tar = next(state, tar)) {
int newState = state ^ ( << tar), nx = next(newState, i);
dfs(newState, nx);
}
} for(int i = ; i < n; ++i)
for(int j = ; j < n; ++j) b[i][j] = c[i][j] = ;
for(int i = ; i < n; ++i) maxb[i] = ; for(int i = ; i < n; ++i) {
if((state & ( << i)) == ) continue;
for(int tar = next(state, i); tar != i; tar = next(state, tar)) {
int newState = state ^ ( << tar), nx = next(newState, i);
maxb[i] = max(maxb[i], dp[nx][newState][i]);
}
for(int tar = next(state, i); tar != i; tar = next(state, tar)) {
int newState = state ^ ( << tar), nx = next(newState, i);
if(sgn(maxb[i] - dp[nx][newState][i]) == ) {
for(int k = ; k < n; ++k) {
++c[i][k];
b[i][k] += dp[nx][newState][k];
}
}
}
for(int k = ; k < n; ++k) b[i][k] /= c[i][k];
} for(int k = ; k < n; ++k) dp[cur][state][k] = p[cur] * b[cur][k]; for(int k = ; k < n; ++k) {
if((state & ( << k)) == ) continue;
int now = cur;
double tmp = , sum = ;
do {
now = next(state, now);
sum += tmp * p[now] * b[now][k];
tmp *= ( - p[now]);
} while(cur != now);
dp[cur][state][k] += sum / ( - tmp) * ( - p[cur]);
}
} void solve() {
dfs(( << n) - , );
for(int i = ; i < n - ; ++i) printf("%.2f ", * dp[][( << n) - ][i]);
printf("%.2f\n", * dp[][( << n) - ][n - ]);
} int main() {
memset(Tnext, -, sizeof(Tnext));
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = ; i < n; ++i) scanf("%lf", &p[i]), p[i] /= ;
for(int i = ; i < n; ++i)
for(int j = ; j < ( << n); ++j) dp[i][j][] = -;
solve();
}
}

POJ 3028 Shoot-out(概率DP)的更多相关文章

  1. poj 3071 Football(概率dp)

    id=3071">http://poj.org/problem? id=3071 大致题意:有2^n个足球队分成n组打比赛.给出一个矩阵a[][],a[i][j]表示i队赢得j队的概率 ...

  2. POJ 2096 Collecting Bugs (概率DP,求期望)

    Ivan is fond of collecting. Unlike other people who collect post stamps, coins or other material stu ...

  3. POJ 2096 Collecting Bugs (概率DP)

    题意:给定 n 类bug,和 s 个子系统,每天可以找出一个bug,求找出 n 类型的bug,并且 s 个都至少有一个的期望是多少. 析:应该是一个很简单的概率DP,dp[i][j] 表示已经从 j ...

  4. poj 2096 Collecting Bugs (概率dp 天数期望)

    题目链接 题意: 一个人受雇于某公司要找出某个软件的bugs和subcomponents,这个软件一共有n个bugs和s个subcomponents,每次他都能同时随机发现1个bug和1个subcom ...

  5. poj 2096 Collecting Bugs 概率dp 入门经典 难度:1

    Collecting Bugs Time Limit: 10000MS   Memory Limit: 64000K Total Submissions: 2745   Accepted: 1345 ...

  6. POJ 3071 Football (概率DP)

    概率dp的典型题.用dp[j][i]表示第j个队第i场赢的概率.那么这场要赢就必须前一场赢了而且这一场战胜了可能的对手.这些都好想,关键是怎么找出当前要算的队伍的所有可能的竞争对手?这个用异或来算,从 ...

  7. POJ 3071 Football:概率dp

    题目链接:http://poj.org/problem?id=3071 题意: 给定n,有2^n支队伍参加足球赛. 给你所有的p[i][j],表示队伍i打败队伍j的概率. 淘汰赛制.第一轮(1,2)两 ...

  8. POJ 2096-Collecting Bugs(概率dp入门)

    题意: 有n种bug和s种系统bug,每天发现一种bug(可能已经发现过了)所有种bug被发现的概率相同,求所有bug被发现的期望天数. 分析: dp[i][j]发现i种bug,j种系统bug期望天数 ...

  9. POJ 3071 Football 【概率DP】

    Football Football Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3734   Accepted: 1908 ...

随机推荐

  1. E. K Balanced Teams

    类比背包问题,为每个学生附加一个权重$pos[i]$,意思是选择该学生后,之后可以选择$p[i]~p[i]+5$的学生. 转换公式: $$d[i][j]=max(d[i+1][q],d[i+pos][ ...

  2. BZOJ2037: [Sdoi2008]Sue的小球(区间DP)

    Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 869  Solved: 483[Submit][Status][Discuss] Description ...

  3. 开发自己的网上支付案例代码(易宝支付php)

    1.简单的图解(如上所示) 易宝支付与支付宝是不一样的,但也有类似之处,支付宝是专门为淘宝软件开发的一套机制,资金会在中间支付公司(支付宝)停留,等待顾客确认,当顾客确认后,才会真正扣钱.而易宝支付时 ...

  4. vue的实例

    vue的实例 创建一个vue实例的写法和创建一个变量一样 var vm = new Vue{{ //我们一般用vm来接收vue的实例,vm是 ViewModel的缩写 }} 然后,我们就可以给vue实 ...

  5. python爬虫学习笔记(1)

    一.请求一个网页内容打印 爬取某个网页: from urllib import request # 需要爬取的网页 url = "https://mbd.baidu.com/newspage ...

  6. Java学习笔记二十五:Java面向对象的三大特性之多态

    Java面向对象的三大特性之多态 一:什么是多态: 多态是同一个行为具有多个不同表现形式或形态的能力. 多态就是同一个接口,使用不同的实例而执行不同操作. 多态性是对象多种表现形式的体现. 现实中,比 ...

  7. ubuntu 防止软件包自动更新

    阻止软件包升级 有两种方法阻止软件包升级,使用dpkg,或者在Woody中使用APT. 使用dpkg,首先导出软件包选择列表: dpkg --get-selections \* > select ...

  8. 第四节 Go数据结构之栈

    一.什么是栈 这是杭州地铁1号线线路图.大卫哥考考大家,地铁列车如何调头? 我也不卖关子了,列车通常是用"人字轨道"来变换车道. 列车先从A轨道开进"人字轨道" ...

  9. 【转】PG数据库高级用法 之 12306 -- 链接

    这么牛的文章很少见,仅附链接,以示敬仰. https://github.com/digoal/blog/blob/master/201611/20161124_02.md

  10. Java设计模式(17)——行为模式之观察者模式(Observer)

    一.概述 概念 UML简图 我们根据一个示例得类图来分析角色 角色 抽象主题:保存观察者聚集(集合),管理(增删)观察者 抽象观察者:定义具体观察者的抽象接口,在得到主题通知后更新自己 具体主题:将有 ...