Codeforces 678E Another Sith Tournament 状压DP
2016-06-15 15:13
232 查看
题意:
有\(n(n \leq 18)\)个人打擂台赛,编号从\(1\)到\(n\),主角是\(1\)号。一开始主角先选一个擂主,和一个打擂的人。
两个人之中胜的人留下来当擂主等主角决定下一个人打擂,败的人退出比赛,直到比赛只剩一个人。
已知任意两人之间决胜的胜率\(P_{ij}\),求主角最终能够获胜的概率。
分析:
设\(d(S, i)\)表示存活的人的集合为\(S\),当前擂主为\(i \in S\),主角获胜的概率。为了方便我们把编号设为\(0 \sim n-1\),递推边界\(d(1,0)=1\)。
考虑\(d(S,i)\),枚举下一个要打擂的人\(k \in S\):
\(P_{ij}\)的概率\(i\)战胜\(j\),擂主为\(i\),状态转移到\(d(S-j,i)\)
\(P_{ji}\)的概率\(j\)战胜\(i\),擂主为\(j\),状态转移到\(d(S-i,j)\)
因为主角可以决定打擂人选\(j\),所以\(d(S,i)=max\{ P_{ij}d(S-j,i) + P_{ji}d(S-i,j) \}\)
最后枚举最开始的擂主,选一个最大值就是答案。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; double p[18][18], d[1 << 18][18]; int main() { int n; scanf("%d", &n); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) scanf("%lf", &p[i][j]); d[1][0] = 1; for(int S = 3; S < (1 << n); S += 2) { for(int i = 0; i < n; i++) if(S&(1<<i)) { for(int j = 0; j < n; j++) if(j != i && (S&(1<<j))) { d[S][i] = max(d[S][i], p[i][j]*d[S^(1<<j)][i] + p[j][i]*d[S^(1<<i)][j]); } } } double ans = 0; for(int i = 0; i < n; i++) ans = max(ans, d[(1<<n)-1][i]); printf("%.15f\n", ans); return 0; }
相关文章推荐
- linux系统相关的任务[fg、bg、jobs、&、ctrl + z]
- 【复习】servlet之生命周期
- Packet Tracer 5.0实验(二) 交换机的Telnet远程登录设置
- memcached学习之slabs部分
- c语言中冒泡排序、插入排序、选择排序算法比较
- tomcat,jetty服务器相关
- 关于Yii框架中不能直接给模型的attributes赋值的解决办法
- cocos2d-x 3.x学习之JumpAction
- 终端下vim无法输入问题解决
- aar引用 no executable code found问题
- JS获取浏览器窗口大小 获取屏幕,浏览器,网页高度宽度
- iOS开发--换肤简单实现以及工具类的抽取
- 内容提供器 Content Provider
- 基于HTML5的视频播放器
- Android View的onTouchEvent和OnTouch区别
- 父子控制器
- cocos2D-X源码分析之从cocos2D-X学习OpenGL(19)----旋转表示法
- 牛客网刷题笔记--左右最值最大差
- 使用python来调试串口
- 学习maven的使用,看到一篇很实用的入门教程(菜鸟级入门)