蓝桥 试题 历届试题 观光铁路

观光铁路

暴力搜索+剪枝

这题很麻烦,一开始找不到很好的办法,大概搜了一下搜到了概率dp,学了一下,发现用不上,因为路径可以无限长,递推没有终点。
然后看到数据量 n ≤ 21 n\le 21 n21,诶数据量好小,那直接搜图吧,DFS递归搜索,然后记录起点,当前点,父节点,当前概率,当前路径长度,遍历子节点,发现父节点跳过,发现起点就可以求当前路径的期望累加到结果里。
但我忽略了环,这个绕起来没完,即使剪枝 p ( n + 1 ) < 1 e − 13 p(n+1)<1e-13 p(n+1)<1e13时间复杂度还是太高了,再剪枝 n < 25 n<25 n<25答案偏离又太多,没法保证1e-9的误差值,难办。

#include
using namespace std;
const int MAX = 100;
int tot = 0, to[MAX], head[MAX], num[MAX], cnext[MAX];
int n, m;
double ans;

void addedge(int u, int v) {
     
	to[++tot] = v;
	cnext[tot] = head[u];
	head[u] = tot;
	num[u]++;
}
void DFS(int c, int u, int f, double p, int n) {
     ;
	if ((p*(n+1)) < 1e-13)return;
	//if (n > 25)return;
	for (int k = head[u]; k; k = cnext[k]) {
     
		int v = to[k];
		if (v == f)continue;
		double np;
		if(f!=0)np = p / (num[u] - 1);
		else np = p / num[u];
		if (v == c) {
      ans += np * (n + 1); continue; }
		DFS(c, v, u, np, n + 1);
	}
}
int main()
{
     
	
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
     
		int u, v;
		cin >> u >> v;
		addedge(u, v);
		addedge(v, u);
	}
    for (int i = 1; i <= n; i++) {
     
		ans = 0;
		DFS(i, i, 0, 1, 0);
		printf("%.12f\n", ans);
	}
	system("pause");
	return 0;
}

规律总结

做着做着发现这个期望可以和图中的度联系起来,这个期望值就正好是图中的总度数比上这个点的度数。具体为什么可能涉及了概率论知识,我先去看看概率论,可能有证明思路了再补上吧。

#include
using namespace std;
const int MAX = 100;
int num[MAX];
int n, m;
int main()
{
     
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
     
		int u, v;
		cin >> u >> v;
		num[u]++;
		num[v]++;
	}
	for (int i = 1; i <= n; i++) {
     
		double p = m * 2.0 / num[i];
		printf("%.12f\n", p);
	}
	return 0;
}

你可能感兴趣的:(题解)