题目来源:http://community.topcoder.com/tc?module=ProblemDetail&rd=15836&pm=12908
参考:http://apps.topcoder.com/wiki/display/tc/SRM+603
这题做的时候完全没思路,看了这里之后才懂了,搞懂这题关键是要想到 在每个点的状态是无记忆性的,即在每个点赢的概率与之前游戏的情况无关。
数组 p[i][t] 表示 从点i出发,最多经过t 轮之后,能赢的概率。只要t足够大,p[i][t]的值就近似是真实值,因为题目要求可以有1e-9的误差。
而p[i][k]的计算又依赖于p[j][k-1]的值,j 表示 可以 i 到达 的点(即graph[i][j] == ‘1‘ ),注意 j 可以 与 i 相同,即点停在原处。有:
p[i][k] = max ( 对所有的 j : w[j] + (1-w[j]-l[j]) * p[j][k-1]).
代码:
#include <algorithm> #include <iostream> #include <sstream> #include <string> #include <vector> #include <stack> #include <deque> #include <queue> #include <set> #include <map> #include <cstdio> #include <cstdlib> #include <cctype> #include <cmath> #include <cstring> using namespace std; /*************** Program Begin **********************/ const int MAX_TURNS = 3000; const int MAX_V = 50; double p[MAX_V][MAX_TURNS + 1]; class GraphWalkWithProbabilities { public: double findprob(vector <string> graph, vector <int> winprob, vector <int> looseprob, int Start) { for (int i = 0; i < MAX_V; i++) { p[i][0] = 0.0; } int N = graph.size(); for (int k = 1; k <= MAX_TURNS; k++) { for (int i = 0; i < N; i++) { p[i][k] = 0.0; for (int j = 0; j < N; j++) { if (graph[i][j] == ‘1‘) { p[i][k] = max( p[i][k], winprob[j] / 100.0 + (100 - winprob[j] - looseprob[j]) / 100.0 * p[j][k-1]); } } } } return p[Start][MAX_TURNS]; } }; /************** Program End ************************/