第一年参加现场赛,比赛的时候就A了这一道,基本全场都A的签到题竟然A不出来,结果题目重现的时候1A,好受打击 ORZ.....
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4800
题目大意:给定C(3,N)支队伍之间对战的获胜概率,再给定一个序列存放队伍编号,每次获胜之后可以选择和当前战胜的对手换队伍。问按给定序列依次挑战全部胜利的最大概率。
解题思路:状压DP
dp[i][j]表示使用队伍i从编号j开始挑战全胜的概率,ai[i]表示i位置的队伍,rate[i][j]表示队伍i战胜队伍j的概率。
状态转移方程:
dp[i][j]=r[i][ai[j]]*max(dp[i][j+1],dp[ai[j]][j+1])
代码如下:

1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define N 10005 8 9 int m,n; 10 int ai[N]; 11 double dp[200][N],rate[200][200]; 12 bool vis[200][N]; 13 14 15 double search(int team,int lo) 16 { 17 if(lo>m-1||team<0||team>n) 18 return 1; 19 if(vis[team][lo]==true) 20 return dp[team][lo]; 21 else 22 { 23 double t=search(team,lo+1); 24 if(team!=ai[lo]) 25 { 26 double t2=search(ai[lo],lo+1); 27 if(t2>t) 28 t=t2; 29 } 30 vis[team][lo]=true; 31 dp[team][lo]=rate[team][ai[lo]]*t; 32 return dp[team][lo]; 33 } 34 } 35 36 37 int main() 38 { 39 int i,j; 40 while(scanf("%d",&n)!=EOF) 41 { 42 n=n*(n-1)*(n-2); 43 n/=6; 44 for(i=0;i<n;i++){ 45 for(j=0;j<n;j++) 46 { 47 scanf("%lf",&rate[i][j]); 48 } 49 } 50 scanf("%d",&m); 51 for(i=0;i<m;i++) 52 scanf("%d",&ai[i]); 53 memset(vis,false,sizeof(vis)); 54 for(i=0;i<n;i++) 55 { 56 dp[i][m-1]=rate[i][ai[m-1]]; 57 vis[i][m-1]=true; 58 } 59 double _max=0; 60 for(i=0;i<n;i++) 61 { 62 _max=max(_max,search(i,0)); 63 } 64 printf("%.6lf ",_max); 65 } 66 return 0; 67 }