(自坑)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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章