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. 阿里云服务器发送邮件失败,25端口被禁用,采用ssl 方式 465端口发送

    /** * 邮件工具类 * User: NZG * Date: 2019/3/8 * Time: 12:25 **/ @Data @Component @Configuration @Configur ...

  2. Linux 学习第五天

    一.重定向.管道符.通配符 1.重定向.管道符使用 重定向: 命令文件 管道符: 命令A:命令B  (管道符  |  别称 “任意门”) 二.常用命令 1.ls /etc | wc -l  (查看目录 ...

  3. 搭建Apache服务器并使用自签证书实现https访问

    实验环境:两台Centos7.2的虚拟机,一台作CA服务器,一台作Apache服务器,此处安装httpd-2.4.6的版本. 1)CA服务器 # 私钥一般存放位置:/etc/pki/CA/privat ...

  4. 高级同步器:可重用的同步屏障Phaser

    引自:https://shift-alt-ctrl.iteye.com/blog/2302923 在JAVA 1.7引入了一个新的并发API:Phaser,一个可重用的同步barrier.在此前,JA ...

  5. jq ajax 传递数组 后台php 接值处理

    //jq数组 var arr = [1,2,3]; //把数组转换为json ajax 传递参数的时候不能直接传递数组 转换为json 可直接传递 var datas = JSON.stringify ...

  6. springboot的junit4模拟request、response对象

    关键字: MockHttpRequest.Mock测试 问题: 在模拟junit的request.response对象时,会报如下空指针异常. 处理方法: 可用MockHttpServletReque ...

  7. h5图片上传简易版(FileReader+FormData+ajax)

    一.选择图片(input的file类型) <input type="file" id="inputImg"> 1. input的file类型会渲染为 ...

  8. PHP 中根据 IP 获取地址

    这里使用的是淘宝 IP 地址库提供的 API 接口. 淘宝 IP 地址库:http://ip.taobao.com/instructions.html API 文档说明:  使用事例: /** * 调 ...

  9. Java : logback简单配置

    需要把logback.xml文件放在类路径下,如果是spring boot项目可以用 logging.config=classpath:log/xxxxxx.xml来指定配置文件 logback la ...

  10. Python学习:5.函数以及基础语句

    函数 一.创建函数 Python的函数的学习是Python基础的一个重要部分,函数可以重复利用,减少代码量,接下来我们就学习一下如何创建一个函数,以及函数的使用. 1.创建一个函数的基本格式 def ...