(POJ 3071)Football(概率DP)
有2^n个人进行比赛,所以可以推出比赛共需要进行n轮,单独考虑第n轮中序号为i的人需要面对的潜在对手,将这些对手分别考虑。
转移方程为dp[i][j]+=dp[k][j-1]*dp[i][j-1]*a[i][k];即晋级的概率=∑(自己来到这一轮的概率*对手来到这一轮的概率*战胜对手的概率)
#include<iostream> #include<cstdio> #include<vector> #include<set> #include<map> #include<string.h> #include<cmath> #include<algorithm> #include<queue> #include<stack> #define LL long long #define mod 1000000007 #define inf 0x3f3f3f3f #define N 20 using namespace std; int poww[8]={1,2,4,8,16,32,64,128}; double dp[130][10]; double a[130][130]; int m,n; void pin() { for(int i=1;i<=n;i++) { if(i&1) dp[i][1]=a[i][i+1]; else dp[i][1]=a[i][i-1]; } for(int j=2;j<=m;j++) { for(int i=1;i<=n;i++) { int l,r; for(int k=poww[j];k<=n;k+=poww[j]) if(i<=k) { r=k; l=k-poww[j]+1; break; } if(i<=r-poww[j-1]) l+=poww[j-1]; else r-=poww[j-1]; for(int k=l;k<=r;k++) dp[i][j]+=a[i][k]*dp[k][j-1]*dp[i][j-1]; } } } int main() { while(~scanf("%d",&m)) { if(m==-1) break; memset(dp,0,sizeof(dp)); memset(a,0,sizeof(a)); n=poww[m]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lf",&a[i][j]); int id; double ans=0; pin(); for(int i=1;i<=n;i++) { if(dp[i][m]>ans) { ans=dp[i][m]; id=i; } } printf("%d\n",id); } return 0; }
此地非逐弃者之王座,彼方乃行愿者之归所。无限清澈,星界银波。