Codeforces 678E. Another Sith Tournament(概率DP,状压)
Codeforces 678E. Another Sith Tournament
题意:
n(n<=18)个人打擂台赛,给定任意两人对决的胜负概率,比赛规则:可指定一人作为最开始的擂主,每次可指定台下的人替代失败的人上去对决,失败的人出局。问在最优决策下,第一个人留到最后的概率。
思路:
首先要观察到这一性质:一号玩家要想取得最终胜利的概率尽可能大,一定要把他安排在最后上场,只打一次。获胜概率与当前擂主以及台下的人有关,所以这个是状态,容易想到需要用二进制表示来压缩状态。
然而想到这些还是不好做,因为如果顺着逻辑正向DP是很困难的,因为每次有输和赢两种走向。因此需要倒着DP。
那么,定义dp[i][sta]:当前存活状态为sta,擂主为i的情况下,一号玩家获胜的最大概率。那么就有了这般转移式:
dp[i][sta] = max{ dp[i][sta], p[i][j] * dp[i][sta^(1<<j)] + p[j][i] * dp[j][sta^(1<<i)] }
这个转移式不是很好理解,想了比较久,觉得这样理解比较好:
对于擂主为i,存活人状态为sta的情况,枚举下一个上台的人j,对于确定的j,状态就有两种走向,i打败j或j打败i。
因此如果我们的决策是指定j上台攻擂,那么上述状态下一号玩家获胜的概率就会等于
pij(i赢j的概率) * dp[i][sta^(1<<j)](j出局,i为擂主的状态下一号玩家获胜概率) + pji(i输给j的概率) * dp[j][sta^(1<<i)](i出局,j成为擂主的状态下一号玩家获胜的概率)。
因此DP转移的顺序应该是倒着的,对于确定的存活状态,再枚举擂主以及攻擂的人,来贪心出怎么转移过去一号玩家获胜概率最大,那么倒着推到n个人都活着的时候,对擂主i枚举,即可贪出最大概率。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<cmath>
#include<functional>
#include<string>
#define dd(x) cout<<#x<<" = "<<x<<" "
#define de(x) cout<<#x<<" = "<<x<<"\n"
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> P;
typedef priority_queue<int> BQ;
typedef priority_queue<int,vector<int>,greater<int> > SQ;
const int maxn=6e5+10,mod=1e9+7,INF=0x3f3f3f3f;
ld p[20][20];
ld dp[20][maxn];
int main()
{int n;cin>>n;for (int i=0;i<n;++i)for (int j=0;j<n;++j)cin>>p[i][j];dp[0][1]=1;for (int sta=1;sta<(1<<n);++sta) {for (int i=0;i<n;++i) {if (!(sta&(1<<i)))continue; for (int j=0;j<n;++j) {if (i==j||!(sta&(1<<j)))continue;dp[i][sta]=max(dp[i][sta], p[i][j]*dp[i][sta^(1<<j)]+p[j][i]*dp[j][sta^(1<<i)]);}}}ld ans=-1;for (int i=0;i<n;++i)ans=max(ans,dp[i][(1<<n)-1]);cout<<setprecision(10)<<ans;return 0;
}
转载于:https://www.cnblogs.com/orangee/p/9844279.html
Codeforces 678E. Another Sith Tournament(概率DP,状压)相关推荐
- SCUT - 254 - 欧洲爆破 - 概率dp - 状压dp
https://scut.online/p/254 思路很清晰,写起来很恶心. #include<bits/stdc++.h> using namespace std; #define l ...
- HDU 4336 概率DP 状压
用d(S)表示所收集到卡片种类状态为S时还需买多少包小浣熊(这是我YY的)的期望. 则有方程d(S) = 1 + (P(空) + P(有)) * d(S) + P(无) * d(T) 其中P(空)表示 ...
- Codeforces 148D. Bag of mice(概率dp)
Codeforces 148D. Bag of mice(概率dp) Description The dragon and the princess are arguing about what to ...
- 【BZOJ】1076 [SCOI2008]奖励关 期望DP+状压DP
[题意]n种宝物,k关游戏,每关游戏给出一种宝物,可捡可不捡.每种宝物有一个价值(有负数).每个宝物有前提宝物列表,必须在前面的关卡取得列表宝物才能捡起这个宝物,求期望收益.k<=100,n&l ...
- Codeforces Round #585 (Div. 2) E. Marbles 状压dp + 逆序对
传送门 文章目录 题意: 思路: 题意: 思路: 考虑数列最终的状态一定是相同颜色在一起,所以我们发现他的颜色是有顺序的!显然可以用状压dpdpdp来枚举颜色的顺序,但是又有问题了,你怎么确定当前这个 ...
- 【BZOJ 4565】 [Haoi2016]字符合并 区间dp+状压
考试的时候由于总是搞这道题导致爆零~~~~~(神™倒序难度.....) 考试的时候想着想着想用状压,但是觉得不行又想用区间dp,然而正解是状压着搞区间,这充分说明了一件事,状压不是只是一种dp而是一种 ...
- #3864. Hero meet devil dp套dp + 状压 + 状态机
传送门 文章目录 题意: 思路: 题意: 给你一个只包含ACGTACGTACGT的串sss,再给你一个mmm,第iii行输出有多少个长度为mmm且只包含ACGTACGTACGT的串与sss的lcslc ...
- [转]状态压缩dp(状压dp)
状态压缩动态规划(简称状压dp)是另一类非常典型的动态规划,通常使用在NP问题的小规模求解中,虽然是指数级别的复杂度,但速度比搜索快,其思想非常值得借鉴. 为了更好的理解状压dp,首先介绍位运算相关的 ...
- CF 221 C Circling Round Treasures - dp - 状压
题目大意: 给你一张网个图,每个位置是空地.障碍.炸弹.宝藏.起点之一. 规划一条从其点出发不包含炸弹的闭合路线(回路),并可获得最大的利润. 利润定义为路线内部的宝藏收益(可能为负数)之和减去路径长 ...
最新文章
- 【Teradata】grouping和rollup窗口函数
- [SHOI2015]自动刷题机
- 「第一篇」大学生电子设计竞赛,等你来提问。
- 关键词是用分号还是逗号隔开_逗号、顿号、分号、冒号、破折号的用法
- windows 下安装nodejs及其配置环境
- JavaScrip节点属性-访问子节点
- 转成静态页面,由于ie网址或路径原因,Atlas失效。
- 看拉扎维《模拟CMOS集成电路设计》的一些总结和思考(五)——无源与有源电流镜
- zend studio php 错误提示,Zend Studio错误总结,zendstudio总结_PHP教程
- Docker 下载redis
- 电动汽车电池换电站选址与定容(Matlab代码实现)
- linux一句话精彩问答 (转贴)
- Android 打造任意层级树形控件 考验你的数据结构和设计
- l计算机中数的表示教案,计算机一级B第一章教案汇总.doc
- html标签指定式权重,alternate和Canonical标签防止重复收录分散权重
- 算法与数据结构学习路线
- 进程的同步和互斥反映了_用信号量解决进程的同步与互斥探讨【持续更新】
- Web应用防火墙WAF简介
- 阿里云域名解析和记录值
- IE5.0中的三个彩蛋(转)
热门文章
- 删除用户和用户下的所有表
- Junit4单元测试报错
- 数据分析系统DIY1/3:CentOS7+MariaDB安装纪实
- 解决Unable to locate theme engine in module_path: pixmap
- 精通Android自定义View(十七)自定义圆形鸟巢加载转圈效果
- memcache单机版安装
- thinkphp 5.0 代码执行漏洞
- java基础—抽象类介绍
- Firefox 浏览器被“http://hao.169x.cn/?m=sov=1023”劫持
- 知识总结: Activity的四种启动模式