题目来源: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 ************************/