题意:题目只有一个case,有16个球队,给出名字,并且下面一个16*16的矩阵,p[i][j]是一个二位的整数,表示i球队打败j球队的概率,p[i][j]+p[j][i]=100,下面16行输出球队名字并且后面一个百分率是该球队获得总冠军的概率
DP递推或者记忆化搜索都可以
设dp[i][left][right]表示i这个球队在第left到第right球队里面得到冠军的概率,所以最后需要的是dp[i][1][16]。一个球队要在当面的阶段得到冠军必须在之前得到冠军
所以mid=(left+right)/2;
i和j在[left,right]里面争夺冠军(例如i和j在1到16里面争夺冠军,也就是争夺总冠军),那么i和j必定是来自于两个分区的
left<=i<=mid , 那么需要得到dp[i][left][mid],dp[j][mid+1][right]
mid+1<=i<=right,那么需要得到dp[i][mid+1][right] , dp[j][left][mid]
具体看代码吧
DP递推
#include <cstdio> #include <cstring> double p[20][20],dp[20][20][20]; char name[20][50]; int main() { int N=16; for(int i=1; i<=N; i++) scanf("%s",name[i]); for(int i=1; i<=N; i++) for(int j=1; j<=N; j++) { scanf("%lf",&p[i][j]); p[i][j]/=100; } int len,left,right,mid,i,j; memset(dp,0,sizeof(dp)); for(int i=1; i<=N; i++) dp[i][i][i]=1; for(len=2; len<=N; len*=2) for(left=1; left<=N; left+=len) { right=left+len-1; mid=(left+right)/2; for(i=left; i<=mid; i++) for(j=mid+1; j<=right; j++) { dp[i][left][right]+=p[i][j]*dp[i][left][mid]*dp[j][mid+1][right]; dp[j][left][right]+=p[j][i]*dp[i][left][mid]*dp[j][mid+1][right]; } } for(i=1; i<=N; i++) printf("%-10s p=%.2f%%\n",name[i],dp[i][1][N]*100); return 0; }
DO记忆化搜索
#include <cstdio> #include <cstring> struct team { char name[110]; int n; }a[20]; double p[20][20]; double dp[20][20][20]; void dfs(int i ,int left ,int right) { if(dp[i][left][right]!=-1) return ; int mid=(left+right)/2; int l1,r1,l2,r2; if(i<=mid) {l1=left; r1=mid; l2=mid+1; r2=right;} else {l1=mid+1; r1=right; l2=left; r2=mid;} dp[i][left][right]=0; for(int j=l2; j<=r2; j++) { dfs(i,l1,r1); dfs(j,l2,r2); dp[i][left][right]+=p[i][j]*dp[i][l1][r1]*dp[j][l2][r2]; } } int main() { int N=16; for(int i=1; i<=N; i++) { scanf("%s",a[i].name); a[i].n=i; } for(int i=1; i<=N; i++) for(int j=1; j<=N; j++) { scanf("%lf",&p[i][j]); p[i][j]/=100; } for(int i=1; i<=N; i++) for(int j=1; j<=N; j++) for(int k=1; k<=N; k++) dp[i][j][k]=-1; for(int i=1; i<=N; i++) dp[i][i][i]=1; int left=1,right=N,mid,l1,r1,l2,r2; mid=(left+right)/2; for(int i=left; i<=right; i++) { if(i<=mid) {l1=left; r1=mid; l2=mid+1; r2=right;} else {l1=mid+1; r1=right; l2=left; r2=mid;} dp[i][left][right]=0.0; for(int j=l2; j<=r2; j++) { dfs(i,l1,r1); dfs(j,l2,r2); dp[i][left][right]+=p[i][j]*dp[i][l1][r1]*dp[j][l2][r2]; } printf("%-10s p=%.2f%%\n", a[i].name , dp[i][left][right]*100); } return 0; }