POJ 3028 Shoot-out(概率DP)

摘要:
当被问及每个人的存活率时,枪手总是会向对他或她最有利的人开枪,但他或她必须向他或她开枪。如果有多个最有益的人,他或她会随机向其中一人开枪。(接下来,每次计算TLE时,预处理后仍然是TLE…)现在我想不出一个好的方法来先做…PS:在创建主题时发布草稿。b[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+1]*b[i+1]+q[i+1]*p[i+1]+2]*b[1+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]+

Description

POJ 3028 Shoot-out(概率DP)第1张

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):

1 #include <cstdio>
2 #include <iostream>
3 #include <algorithm>
4 #include <cstring>
5 using namespacestd;
6 typedef long longLL;
7 
8 const int MAXN = 13;
9 const double EPS = 1e-8;
10 
11 intT, n;
12 double dp[MAXN][(1 << MAXN) + 10][MAXN];
13 doublep[MAXN];
14 
15 inline int sgn(doublex) {
16     return (x > EPS) - (x < -EPS);
17 }
18 
19 int Tnext[1 <<MAXN][MAXN];
20 
21 inline int next(int state, intx) {
22     if(Tnext[state][x] != -1) returnTnext[state][x];
23     int ret =x;
24     while(true) {
25         if(++ret == n) ret = 0;
26         if(state & (1 << ret)) break;
27 }
28     return Tnext[state][x] =ret;
29 }
30 
31 inline int count(intstate) {
32     int ret = 0;
33     while(state) {
34         ret += state & 1;
35         state >>= 1;
36 }
37     returnret;
38 }
39 
40 intc[MAXN][MAXN];
41 doubleb[MAXN][MAXN], maxb[MAXN];
42 
43 void dfs(int state, intcur) {
44     if(dp[cur][state][0] != -1) return;
45     if(count(state) == 1) {
46         for(int i = 0; i < n; ++i) dp[cur][state][i] = (i ==cur);
47         return;
48 }
49 
50     for(int i = 0; i < n; ++i) {
51         if((state & (1 << i)) == 0) continue;
52         for(int tar = next(state, i); tar != i; tar =next(state, tar)) {
53             int newState = state ^ (1 << tar), nx =next(newState, i);
54 dfs(newState, nx);
55 }
56 }
57 
58     for(int i = 0; i < n; ++i)
59         for(int j = 0; j < n; ++j) b[i][j] = c[i][j] = 0;
60     for(int i = 0; i < n; ++i) maxb[i] = 0;
61 
62     for(int i = 0; i < n; ++i) {
63         if((state & (1 << i)) == 0) continue;
64         for(int tar = next(state, i); tar != i; tar =next(state, tar)) {
65             int newState = state ^ (1 << tar), nx =next(newState, i);
66             maxb[i] =max(maxb[i], dp[nx][newState][i]);
67 }
68         for(int tar = next(state, i); tar != i; tar =next(state, tar)) {
69             int newState = state ^ (1 << tar), nx =next(newState, i);
70             if(sgn(maxb[i] - dp[nx][newState][i]) == 0) {
71                 for(int k = 0; k < n; ++k) {
72                     ++c[i][k];
73                     b[i][k] +=dp[nx][newState][k];
74 }
75 }
76 }
77         for(int k = 0; k < n; ++k) b[i][k] /=c[i][k];
78 }
79 
80     for(int k = 0; k < n; ++k) dp[cur][state][k] = p[cur] *b[cur][k];
81 
82     for(int k = 0; k < n; ++k) {
83         if((state & (1 << k)) == 0) continue;
84         int now =cur;
85         double tmp = 1, sum = 0;
86         do{
87             now =next(state, now);
88             sum += tmp * p[now] *b[now][k];
89             tmp *= (1 -p[now]);
90         } while(cur !=now);
91         dp[cur][state][k] += sum / (1 - tmp) * (1 -p[cur]);
92 }
93 }
94 
95 voidsolve() {
96     dfs((1 << n) - 1, 0);
97     for(int i = 0; i < n - 1; ++i) printf("%.2f ", 100 * dp[0][(1 << n) - 1][i]);
98     printf("%.2f
", 100 * dp[0][(1 << n) - 1][n - 1]);
99 }
100 
101 intmain() {
102     memset(Tnext, -1, sizeof(Tnext));
103     scanf("%d", &T);
104     while(T--) {
105         scanf("%d", &n);
106         for(int i = 0; i < n; ++i) scanf("%lf", &p[i]), p[i] /= 100;
107         for(int i = 0; i < n; ++i)
108             for(int j = 0; j < (1 << n); ++j) dp[i][j][0] = -1;
109 solve();
110 }
111 }
View Code

免责声明:文章转载自《POJ 3028 Shoot-out(概率DP)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇[JDK8]Map接口与Dictionary抽象类SpringBoot打成jar后无法读取根路径和文件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

IDEA工作空间多开项目教程,多个项目放在一起

  刚开始使用IDEA的时候,因为不知道能在一个工作空间运行多个项目,都是有几个项目就开几个页面,结果就是,电脑超卡,本来电脑的运行就不大,这下子就更卡了,经常敲着敲着就卡顿了, 所以在知道能开一个页面之后,这个博文就出来了,下面就是具体的操作步骤:      1.打开IDEA → 选择 【file】→【new】→[Project]          ...

python- generator生成器

什么是生成器? 通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的,而且创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的l...

tar: vmware-tools-distrib:Cannot mkdir: Read-only file System 问题

这一般是全新问题,把 vmware tools.tar.gz 文件复制到其他目录,就可以进行解压了 cp /media/tommy/VMware Tools/VMwareTools-10.3.21-14772444.tar.gz /tmp cd /tmp tar zxvf VMwareTools-10.3.21-14772444.tar.gz 参考: 解决...

约瑟夫生死游戏(单链表实现)

本周的作业还算挺好玩。。约瑟夫生死游戏嘛。 老师要抽签选择每个组对应的数据结构。结果宝宝抽到了单链表。。。。 一、项目简介       约瑟夫生者死者游戏的大意是:30个旅客同乘一条船,因为严重超载,加上风高浪大,危险万分;因此船长告诉乘客,只有将全船一半的旅客投入海中,其余人才能幸免遇难。无奈,大家只得同意这种办法,并议定30个人围成一圈,由第一个人开始...

CentOS+Nginx+PHP+Mysql 服务器配置

[利用yum命令配置、升级所需程序库] # sudo -s# LANG=C# yum -y install gcc gcc-c++ autoconf #yum -y install make //如果不安装make,那么cmake的时候会出问题 # yum -y install cmake # yum -y install bison 接下来最好手动编译...

nginx proxy_next_upstream 与openresty balancer.set_more_tries的使用

背景 我们这边网关服务使用的 kong,前段时间上线一个服务,这个服务它报错了,产生了502的错误码,追查这个报错的时候发现了网关服务的两个可疑的地方,第一个疑点是我们在Kong上配置的 Retries = 5,但是实际实际上我们的代理重试至多只会重试三次。第二个疑点是我们的重试只重试了502 和 504,大量的500错误没有重试。带着这两个问题了查了下k...