(自坑)HUD 5001 暴力/dp

Walk

Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 267    Accepted Submission(s): 184
Special Judge


Problem Description
I used to think I could be anything, but now I know that I couldn't do anything. So I started traveling.

The nation looks like a connected bidirectional graph, and I am randomly walking on it. It means when I am at node i, I will travel to an adjacent node with the same probability in the next step. I will pick up the start node randomly (each node in the graph has the same probability.), and travel for d steps, noting that I may go through some nodes multiple times.

If I miss some sights at a node, it will make me unhappy. So I wonder for each node, what is the probability that my path doesn't contain it.
 

Input
The first line contains an integer T, denoting the number of the test cases.

For each test case, the first line contains 3 integers n, m and d, denoting the number of vertices, the number of edges and the number of steps respectively. Then m lines follows, each containing two integers a and b, denoting there is an edge between node a and node b.

T<=20, n<=50, n-1<=m<=n*(n-1)/2, 1<=d<=10000. There is no self-loops or multiple edges in the graph, and the graph is connected. The nodes are indexed from 1.
 

Output
For each test cases, output n lines, the i-th line containing the desired probability for the i-th node.

Your answer will be accepted if its absolute error doesn't exceed 1e-5.
 

Sample Input
2 5 10 100 1 2 2 3 3 4 4 5 1 5 2 4 3 5 2 5 1 4 1 3 10 10 10 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 4 9
 

Sample Output
0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.0000000000 0.6993317967 0.5864284952 0.4440860821 0.2275896991 0.4294074591 0.4851048742 0.4896018842 0.4525044250 0.3406567483 0.6421630037
 

Source
 

題目大意:

給出n個點,m條雙向邊,d步。在每個點向與其相鄰點移動的可能性相等,開始時每個點被選取作爲起點的可能性相等。

問,所有的路徑中不經過每個點的概率是多少。


反省&思路:

首先,在打這場網絡賽的時候 , 犯了很嚴重的失誤———沒有好好審視好這道題的時限——15s是個人都能寫個暴力程序過掉啊~!!!


思路的話,直接計算n次,每次只求出在每一步中其他每一個不經過當前刪除點的的概率。

遞推式爲: 

dp[k][j]表示在第j步走到k時前j步都沒經過x的概率,

那麼在某一步j中對於非x的每一個點k有

dp[k][j]=sigema(dp[kk][j-1] * (num[kk]/1))   其中kk是與k 相鄰的點,num[kk]表示與kk相鄰的點的個數



WA的原因:

由於手寫靜態鄰接鏈表不是很熟悉,導致:

(1)數組開小

(2)在遍歷臨街表的那個for裏面,把kk和G[kk].to搞混


詳細錯誤的話,看下面的代碼有註釋標出




下面是ac代碼

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <numeric>
#include <functional>
#define maxn 60
#define maxm 6000   //WA的罪魁禍首

using namespace std;
int t;
int n,m,d;
//vector<int> G[maxn];
int head[maxn],si;
struct edge{int to,next;} G[maxm];
double dp[60][10008],num[maxn];  //dp[i][j] 在第j步到達i點但是之前j步不經過now的概率

void addedge(int from,int to)
{
    G[si].to=to;
    G[si].next=head[from];
    head[from]=si++;
}

void init(int now)
{
    for(int i=0;i<n;i+=1){
        for(int j=0;j<=d;j+=1){
            dp[i][j]=0;
        }
    }
    for(int i=0;i<n;i+=1){
        if(i!=now)
            dp[i][0]=1/(double)n;
    }
}

int main()
{
    cin>>t;
    while(t--){
        cin>>n>>m>>d;
        int a,b;
        memset(head,-1,sizeof head);
        memset(num,0,sizeof num);
        si=0;
        for(int i=0;i<m;i+=1){
            cin>>a>>b;
            num[a-1]+=1;
            num[b-1]+=1;
            addedge(a-1,b-1);
            addedge(b-1,a-1);
        }

        for(int i=0;i<n;i+=1){
            init(i);
            double res=0;
            for(int j=1;j<=d;j+=1){
                for(int k=0;k<n;k+=1){
                    for(int kk=head[k];k!=i&&kk!=-1;kk=G[kk].next){
                        if(/*kk!=i*/G[kk].to!=i)
                        //最根本的WA的原因是數組開小了,後來想來想去加了這個步驟,最後改了數組加了這步還是WA
                        //後來發現時註釋裏面的逗比錯誤,用if註釋外的就必然過了
                            dp[k][j]+=(dp[G[kk].to][j-1]*(1/num[G[kk].to]));
                        else
                            cout<<"____"<<dp[i][j]<<endl;
                    }
                }
            }

            for(int j=0;j<n;j+=1){
                if(j!=i)       //漏1
                    res+=dp[j][d];
            }
            printf("%.10lf\n",res);
        }
    }

    return 0;
}




發佈了91 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章