cogs 943. [東方S3] 铃仙•优昙华院•稻叶

二次联通门 : cogs 943. [東方S3] 铃仙•优昙华院•稻叶

/*
    cogs 943. [東方S3] 铃仙·优昙华院·稻叶

    概率dp
    
    貌似做麻烦了
    邻接矩阵和链式前向星都用上了。。。
    
    dp[pos][i][j]表示 第i秒 在i点 上一个经过的点是j
    方程: 
    dp[pos][i][j]=Σdp[pos-1][j][k]*(__out[j]+1-(map[j][k]==1))+dp[pos-1][i][j]*(__out[i]+1-(map[i][j]==1)

    前面的求和考虑的是上一秒从其他的一个节点走过来 
    后面的考虑的是上一秒选择停留在原地
    
    复杂度O(T * N^3) 
    
*/
#include <cstdio>
 
void read (int &now)
{
    register char word = getchar ();
    for (now = 0; word < '0' || word > '9'; word = getchar ());
    for (; word >= '0' && word <= '9'; now = now * 10 + word - '0', word = getchar ());
}
 
#define Max 55
bool map[Max][Max];
int __out[Max * 200];
 
double dp[Max * 10][Max][Max];
 
int __next[Max * 200];
int __to[Max * 200];
 
int edge_list[Max * 200];
int Edge_Count ;
 
inline void AddEdge (int from, int to)
{
    Edge_Count ++;
    __next[Edge_Count] = edge_list[from];
    __to[Edge_Count] = to;
    edge_list[from] = Edge_Count;
    
}
int main (int argc, char *argv[])
{
    freopen ("reisen.in", "r", stdin);
    freopen ("reisen.out", "w", stdout);
    int N, M, T;
    read (N);
    read (M);
    read (T);
    int x, y;
    for (register int i = 1; i <= M; i ++)
    {
        read (x);
        read (y);
        map[x][y] = true;
        __out[x] ++;
        AddEdge (x, y);
    }
    dp[0][1][1] = 1.00;
    register bool flag;
    for (register int pos = 0, i, j, Flan; pos <= T; pos ++)
        for (i = 1; i <= N; i ++)
            for (j = 1; j <= N; j ++)
                if (dp[pos][i][j] > 0.00)
                {
                    flag = false;
                    if (map[i][j])
                        flag = true;
                    for (Flan = edge_list[i]; Flan; Flan = __next[Flan])
                    {
                        if (__to[Flan] == j)
                            continue;
                        dp[pos + 1][__to[Flan]][i] += dp[pos][i][j] * 1.00 / (double)(__out[i] + !flag);
                    }
                    dp[pos + 1][i][j] += dp[pos][i][j] * 1.00 / (double)(__out[i] + !flag);
                }
    register double Answer;
    
    for (register int i = 1, j; i <= N; i ++)
    {
        Answer = 0.00;
        for (j = 1; j <= N; j ++)
            Answer += dp[T][i][j];
        printf ("%.3lf
", Answer * 100);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ZlycerQan/p/7193323.html