HDU 4800/zoj 3735 Josephina and RPG 2013 长沙现场赛J题

第一年参加现场赛,比赛的时候就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 }
View Code
原文地址:https://www.cnblogs.com/wuwing/p/3452802.html