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
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.
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.
Your answer will be accepted if its absolute error doesn't exceed 1e-5.
題目大意:
給出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;
}