題目:http://community.topcoder.com/stat?c=problem_statement&pm=13117&rd=15950
看到樹,又是與節點有關,一般是dp,dp[v][t] 表示在以v為root的subtree上有t個eagle時滿足條件的機率。一個注意點是求二項系數數組C[]時,因為值太大,要用double,不能用long long, long long 會溢出。
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <bitset>
#include <string>
#include <vector>
#include <stack>
#include <deque>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <ctime>
#include <climits>
using namespace std;
#define CHECKTIME() printf("%.2lf\n", (double)clock() / CLOCKS_PER_SEC)
typedef pair<int, int> pii;
typedef long long llong;
typedef pair<llong, llong> pll;
#define mkp make_pair
/*************** Program Begin **********************/
const int MAX_N = 51, MAX_K = 101;
double dp[MAX_N][MAX_K];
double C[MAX_K][MAX_K]; // 二項系數,注意:用 long long 會溢出
class EagleInZoo {
public:
vector < vector<int> > childs;
double rec(int v, int t)
{
if (1 == t) {
return 1.0;
}
double & res = dp[v][t];
if (res > -0.5) {
return res;
}
if (childs[v].size() == 0 && t > 1) { // 該節點無 child 且t > 1,最後一隻一定無法停留
res = 0;
return res;
}
res = 0;
for (int i = 0; i < childs[v].size(); i++) {
int x = childs[v][i];
int c = childs[v].size();
for (int j = 0; j <= t - 2; j++) {
res += (1.0 / c) * C[t-2][j] * pow(1.0 / c, j) * pow( 1.0 * (c-1) / c, t-2-j) * rec(x, j + 1);
}
}
return res;
}
double calc(vector <int> parent, int K) {
for (int i = 0; i < MAX_N; i++) {
for (int j = 0; j < MAX_K; j++) {
dp[i][j] = -1.0;
}
}
childs.resize(parent.size() + 1);
for (int i = 0; i < parent.size(); i++) {
childs[ parent[i] ].push_back(i + 1);
}
// calculate C[]
C[0][0] = 1;
for (int i = 1; i <= K - 1; i++) {
C[i][0] = C[i][i] = 1;
for (int j = 1; j < i; j++) {
C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
}
}
return rec(0, K);
}
};
/************** Program End ************************/