首页 > 代码库 > poj3071(概率DP)
poj3071(概率DP)
题意:淘汰赛制,2^n(n<=7)个队员.给出相互PK的输赢概率矩阵。问谁最有可能赢到最后。
解法:ans[i][j]表示第i个队员第j轮胜出的概率。赢到最后需要进行n场比赛。算出每个人赢到最后的ans[i][n]。写出序号的二进制发现一个规律,两个队员i、j如果碰到,那么一定是在第get(i,j)场比赛碰到的。get(i,j)计算的是i和j二进制不同的最高位,这个规律也比较明显。
代码:
/****************************************************** * author:xiefubao *******************************************************/ #pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <vector> #include <algorithm> #include <cmath> #include <map> #include <set> #include <stack> #include <string.h> //freopen ("in.txt" , "r" , stdin); using namespace std; #define eps 1e-8 const double pi=acos(-1.0); typedef long long LL; const int Max=500; const int INF=1000000007; int n; double num[Max][Max]; bool rem[Max][Max]; double ans[Max][10]; int get(int i,int j) { for(int k=n-1;k>=0;k--) { if((i&(1<<k))^(j&(1<<k))) return k; } } int main() { while(scanf("%d",&n)==1) { memset(ans,0,sizeof ans); memset(rem,0,sizeof rem); if(n==-1) break; for(int i=0; i<(1<<n); i++) for(int j=0; j<(1<<n); j++) scanf("%lf",num[i]+j); for(int i=0;i<(1<<n);i++) ans[i][0]=1.0; for(int k=0;k<n;k++) { for(int i=0;i<(1<<n);i++) for(int j=i+1;j<(1<<n);j++) { int t=get(i,j); if(t!=k)continue; ans[i][k+1]+=ans[j][k]*ans[i][k]*num[i][j]; ans[j][k+1]+=ans[i][k]*ans[j][k]*num[j][i]; } } double t=0; double sum=0; int out=0; for(int i=0;i<(1<<n);i++) { if(t<ans[i][n]) { t=ans[i][n]; out=i; } } cout<<out+1<<endl; } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。