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. 在IDEA中关于项目java版本问题

    在IDEA中关于项目java版本问题 当出现错误如:java无效的源发行版11或IDEA Error:java:Compliation failed:internal java complier er ...

  2. nginx ssl pathinfo 伪静态 301 配置文件

    server { listen ; root /www/web/test_com/public_html; server_name test.com test.com; if ($host != '* ...

  3. JZOJ 4273. 【NOIP2015模拟10.28B组】圣章-精灵使的魔法语

    4273. [NOIP2015模拟10.28B组]圣章-精灵使的魔法语 (File IO): input:elf.in output:elf.out Time Limits: 1000 ms  Mem ...

  4. 大数据学习--day03(运算符、流程控制语句)

    运算符.流程控制语句 自增自减容易出错的地方: 扩展的赋值运算符  a+=b 等同于 a = a+b;  扩展的赋值运算符 隐含了一个类型的强制转换 & && 有何区别   & ...

  5. openWrt libubox组件之uloop原理分析

    1.    libubox概述 libubox是openwrt新版本中的一个基础库,有很多应用是基于libubox开发的,如uhttpd,netifd,ubusd等. libubox主要提供以下两种功 ...

  6. pymyspl模块

    pymysql的下载和使用 该模块本质就是一个套接字客户端软件,使用前需要事先安装,能够让我们在 Python程序中操作数据库. pymysql模块的下载: 在Python安装文件中找到scripts ...

  7. 几个简单if程序的细节比较与加法程序设计

    关于简单的if判断语句的不同写法: 输出0-9十个整数: 第一个程序: #include<stdio.h> #include<stdlib.h> int main() { ; ...

  8. win10 禁用自动更新

    管理员身份运行CMD,输入REG add "HKLM\SYSTEM\CurrentControlSet\Services\UsoSvc" /v "Start" ...

  9. java入门---对象和类&概念详解&实例

        Java作为一种面向对象语言.支持以下基本概念: 多态 继承 封装 抽象 类 对象 实例 方法 重载     这篇文章,我们主要来看下: 对象:对象是类的一个实例(对象不是找个女朋友),有状态 ...

  10. git忽略项gitegnore配置

    在git中如果想忽略掉某个文件, 不让这个文件提交到版本库中,可以使用修改 .gitignore 文件的方法.这个文件每一行保存了一个匹配的规则 例如 # 此为注释 – 将被 Git 忽略 *.a # ...