[Noi2005]聪聪和可可

Description

Input

数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数。第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号。接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路。所有的路都是无向的,即:如果能从A走到B,就可以从B走到A。输入保证任何两个景点之间不会有多于一条路直接相连,且聪聪和可可之间必有路直接或间接的相连。

Output

输出1个实数,四舍五入保留三位小数,表示平均多少个时间单位后聪聪会把可可吃掉。

Sample Input

【输入样例1】

4 3

1 4

1 2

2 3

3 4

【输入样例2】

9 9

9 3

1 2

2 3

3 4

4 5

3 6

4 6

4 7

7 8

8 9

Sample Output

【输出样例1】

1.500

【输出样例2】

2.167

HINT

【样例说明1】

开始时,聪聪和可可分别在景点1和景点4。

第一个时刻,聪聪先走,她向更靠近可可(景点4)的景点走动,走到景点2,然后走到景点3;假定忽略走路所花时间。

可可后走,有两种可能:

第一种是走到景点3,这样聪聪和可可到达同一个景点,可可被吃掉,步数为1,概率为 。

第二种是停在景点4,不被吃掉。概率为 。

到第二个时刻,聪聪向更靠近可可(景点4)的景点走动,只需要走一步即和可可在同一景点。因此这种情况下聪聪会在两步吃掉可可。

所以平均的步数是1* +2* =1.5步。

对于所有的数据,1≤N,E≤1000。

对于50%的数据,1≤N≤50。

第一道概率dp的题,首先要对每一个点bfs一下, 预处理出从i到j的最短路上,i下一步会走到的点p[i][j];

设dp[i][j]表示聪聪在i,可可在j时聪聪可以吃到可可平均要走的次数

如果p[i][j] == j || p[ p[i][j] ][j] == j,则dp[i][j] = 1,

如果i == j  dp[i][j] = 0;

其他情况: 令u = p[ p[i][j] ][j]

dp[i][j] = ((dp[u][j] + 1)+ sigma(dp[u][k] (k与点j相连) + 1)) / (deg[j] + 1)

deg[j] 是点j的度数

#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
const int N = 1010;
int n, m;
int p[N][N];
int dist[N];
double dp[N][N];
int deg[N];
int head[N];
int tot;

struct node
{
	int next;
	int to;
}edge[N << 2];

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

void short_distance()
{
	queue <int> qu;
	for (int i = 1; i <= n; ++i)
	{
		while (!qu.empty())
		{
			qu.pop();
		}
		memset (dist, 0x3f3f3f3f, sizeof(dist));
		dist[i] = 0;
		qu.push(i);
		p[i][i] = i;
		while (!qu.empty())
		{
			int u = qu.front();
			qu.pop();
			for (int j = head[u]; ~j; j = edge[j].next)
			{
				int v = edge[j].to;
				if (dist[v] > dist[u] + 1 ||(u < p[v][i] && dist[v] == dist[u] + 1))
				{
					p[v][i] = u;
					dist[v] = dist[u] + 1;
					qu.push(v);
				}
			}
		}
	}
}

double dfs(int i, int j)
{
	if (i == j)
	{
		return dp[i][j] = 0;
	}
	if (p[i][j] == j || p[ p[i][j] ][j] == j)
	{
		return dp[i][j] = 1;
	}
	if (dp[i][j] != -1)
	{
		return dp[i][j];
	}
	double cur = 0;
	int u = p[ p[i][j] ][j];
	cur = dfs(u, j) + 1; //可可留在原地
	for (int k = head[j]; ~k; k = edge[k].next)
	{
		cur += dfs(u, edge[k].to) + 1;
	}
	cur /= (deg[j] + 1);
	return dp[i][j] = cur;
}

int main()
{
	int s, e;
	while (~scanf("%d%d", &n, &m))
	{
		scanf("%d%d", &s, &e);
		int u, v;
		memset (head, -1, sizeof(head));
		memset (deg, 0, sizeof(deg));
		tot = 0;
		for (int i = 1; i <= m; ++i)
		{
			scanf("%d%d", &u, &v);
			addedge(u, v);
			addedge(v, u);
			deg[u]++;
			deg[v]++;
		}
		for (int i = 1; i <= n; ++i)
		{
			dp[i][i] = 0;
			for (int j = 1; j <= n; ++j)
			{
				if (i == j)
				{
					continue;
				}
				dp[i][j] = -1;
			}
		}
		short_distance();
		dfs(s, e);
		printf("%.3f\n", dp[s][e]);
	}
	return 0;
}
时间: 2024-12-17 18:56:56

[Noi2005]聪聪和可可的相关文章

bzoj1415【NOI2005】聪聪和可可

1415: [Noi2005]聪聪和可可 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1271  Solved: 748 [Submit][Status][Discuss] Description Input 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景

【BZOJ】【1415】【NOI2005】聪聪和可可

数学期望+记忆化搜索 论文:<浅析竞赛中一类数学期望问题的解决方法>——汤可因  中的第一题…… Orz 黄学长 我实在是太弱,这么简单都yy不出来…… 宽搜预处理有点spfa的感觉= =凡是更新了的,都要重新入队更新一遍…… dp的记忆化搜索过程好厉害…… 期望这里一直很虚啊,赶紧再多做点题熟悉熟悉…… 1 /************************************************************** 2 Problem: 1415 3 User: Tunix

【BZOJ 1415】 1415: [Noi2005]聪聪和可可 (bfs+记忆化搜索+期望)

1415: [Noi2005]聪聪和可可 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1640  Solved: 962 Description Input 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路. 所有的路都是无向的,即

【NOI2005】聪聪与可可

P2432 - [NOI2005]聪聪与可可 Description 在一个魔法森林里,住着一只聪明的小猫聪聪和一只可爱的小老鼠可可.虽然灰姑娘非常喜欢她们俩,但是,聪聪终究是一只猫,而可可终究是一只老鼠,同样不变的是,聪聪成天想着要吃掉可可. 一天,聪聪意外得到了一台非常有用的机器,据说是叫GPS,对可可能准确的定位.有了这台机器,聪聪要吃可可就易如反掌了.于是,聪聪准备 马上出发,去找可可.而可怜的可可还不知道大难即将临头,仍在森林里无忧无虑的玩耍.小兔子乖乖听到这件事,马上向灰姑娘报告.灰

【BZOJ1415】【NOI2005】聪聪和可可(动态规划,数学期望)

[BZOJ1415][NOI2005]聪聪和可可(动态规划,数学期望) 题面 BZOJ 题解 先预处理出当可可在某个点,聪聪在某个点时 聪聪会往哪里走 然后记忆化搜索一下就好了 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #i

Bzoj1415 [Noi2005]聪聪和可可

Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1586  Solved: 929 Description Input 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路. 所有的路都是无向的,即:如果能从A走到B,就可以从B走到A. 输

BZOJ 1415 NOI2005 聪聪和可可 期望DP+记忆化搜索 BZOJ200题达成&amp;&amp;NOI2005全AC达成

题目大意:给定一个无向图,聪聪在起点,可可在终点,每个时刻聪聪会沿最短路走向可可两步(如果有多条最短路走编号最小的点),然后可可会等概率向周围走或不动,求平均多少个时刻后聪聪和可可相遇 今天早上起床发现194了然后就各种刷--当我发现199的时候我决定把第200题交给05年NOI仅剩的一道题--结果尼玛调了能有一个小时--我居然没看到编号最小这个限制0.0 首先我们知道,由于聪聪走两步而可可走一步,所以聪聪一定能在有限的时刻追上可可,而且两人的距离随着时间进行单调递减 于是我们记忆化搜索 首先用

【NOI2005】 聪聪可可

树分治劲啊 原题: 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)--遇到这种问题,一般情况下石头剪刀布就好了,可是他们已经玩儿腻了这种低智商的游戏.他们的爸爸快被他们的争吵烦死了,所以他发明了一个新游戏:由爸爸在纸上画n个"点",并用n-1条"边"把这n个"点"恰好连通(其实这就是一棵树).并且每条"边"上都有一个数.接下来由聪聪和可可分

BZOJ 1415 【NOI2005】 聪聪和可可

题目链接:聪聪和可可 一道水题--开始还看错题了,以为边带权--强行\( O(n^3)\)预处理-- 首先,我们显然可以预处理出一个数组\( p[u][v] \)表示可可在点\(u\),聪聪在点\(v\)的时候聪聪下一步会往哪里走.然后--一个记忆化搜索就轻易地解决掉了-- 至于转移方程吗,我觉得也没有必要写了--你要是实在不知道就看一看代码吧-- 下面贴代码: #include<iostream> #include<cstdio> #include<cstring>

Vijos1675 NOI2005 聪聪和可可 记忆化搜索

简单题,结果因为理解错题意懵逼了好久…… moveTo[x][y]表示聪聪在节点x,可可在节点y时,聪聪下一步应到达哪一个节点 dp[x][y]表示聪聪在节点x,可可在节点y,且轮到可可行动时,所需时间的数学期望(可可第一次行动不计入其内) 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 #include <queue> 6