- https://codeforces.com/contest/678/problem/E
思路:
- 这个概率dp正着方向来算很麻烦,因为可以改变这个选手比赛的顺序(假设擅长的次序为p0,p1,p2,p3,...,pn)
- 定义f[mask][i]为在mask状态下,赢家是i,mask在二进制上1表示已经上过场或者正在场上,0表示还未上过场
- 状态转移:从终点f[1][0] = 1出发(因为要计算的概率是在让1号胜利的最大可能性上的),推导f[(1<<n)-1][0~n-1]中的最大值就是答案
- 具体计算可以从2开始枚举mask,每次找到任意两个在擂台上的人,加上两个人互相击败的,但是赢家不变的情况
- 此题难度较高,思维和代码能力缺一不可
#include<bits/stdc++.h> #define debug1(a) cout<<#a<<'='<< a << endl; #define debug2(a,b) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<endl; #define debug3(a,b,c) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<endl; #define debug4(a,b,c,d) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<" "<<#d<<" = "<<d<<endl; #define debug5(a,b,c,d,e) cout<<#a<<" = "<<a<<" "<<#b<<" = "<<b<<" "<<#c<<" = "<<c<<" "<<#d<<" = "<<d<<" "<<#e<<" = "<<e<<endl; #define endl "\n" #define fi first #define se second #define int long long using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef pair<LL,LL> PLL; //#pragma GCC optimize(3,"Ofast","inline") //#pragma GCC optimize(2) const int N = 20; double a[N][N]; double f[1<<N][N];//f[i][j]表示状态为i(0上过擂台后已死亡,1表示存活)的情况下,j是当前状态的赢家(j+1) void solve() { int n;cin >> n; for(int i = 0;i < n;i ++) { for(int j = 0;j < n;j ++) { cin >> a[i][j]; } } f[1][0] = 1;//最后的结果,逆推回初始状态max(f[(1<<n)-1][j]),全部存活,且第一个上场的人 for(int mask = 2;mask < 1 << n; mask ++) { for(int i = 0;i < n;i ++)if(mask >> i & 1) { for(int j = 0;j < n;j ++)if(j != i && (mask >> j & 1)) { f[mask][i] = max(f[mask][i],f[mask ^ (1<<i)][j] * a[j][i] + f[mask^(1<<j)][i] * a[i][j]); } } } double ans = 0; for(int i = 0;i < n;i ++) { ans = max(ans,f[(1<<n)-1][i]); } printf("%.7lf",ans); } signed main() { /* ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); */ int T = 1;//cin >> T; while(T--){ //puts(solve()?"YES":"NO"); solve(); } return 0; } /* */
标签:GCC,概率,int,mask,++,dp From: https://www.cnblogs.com/cfddfc/p/17056428.html