【bzoj1415】[Noi2005]聪聪和可可 期望记忆化搜索
题目描述
输入
数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数。 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号。 接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路。 所有的路都是无向的,即:如果能从A走到B,就可以从B走到A。 输入保证任何两个景点之间不会有多于一条路直接相连,且聪聪和可可之间必有路直接或间接的相连。
输出
输出1个实数,四舍五入保留三位小数,表示平均多少个时间单位后聪聪会把可可吃掉。
样例输入
【输入样例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
样例输出
【输出样例1】
1.500
【输出样例2】
2.167
题解
期望记忆化搜索
先预处理出两个点之间的最短路,以及从那个点走来。
然后就是很水的期望dp。
设f[i][j]表示聪聪在i,可可在j时还要走的期望时间。
那么显然考虑i走两步到达的点t,f[i][j]=∑dis[j][k]≤1f[t][k]d[j]+1。
由于两人距离一定是越来越小的,所以这个dp实际上是有序的(按照两点距离从小到大)。为了不特殊处理顺序,使用记忆化搜索就好了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include <queue> #include <cstdio> #include <algorithm> #define N 1010 using namespace std; queue< int > q; int d[N] , head[N] , to[N << 1] , next[N << 1] , cnt , last[N][N] , dis[N][N]; double f[N][N]; void add( int x , int y) { to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt , d[x] ++ ; } void bfs( int u) { int x , i; last[u][u] = -1 , q.push(u); while (!q.empty()) { x = q.front() , q.pop(); for (i = head[x] ; i ; i = next[i]) { if (!last[u][to[i]]) last[u][to[i]] = x , dis[u][to[i]] = dis[u][x] + 1 , q.push(to[i]); else if (dis[u][to[i]] == dis[u][x] + 1 && last[u][to[i]] > x) last[u][to[i]] = x; } } } double dfs( int x , int y) { if (dis[x][y] == 0) return 0; if (f[x][y] > 0) return f[x][y]; if (dis[x][y] <= 2) return f[x][y] = 1; int t = last[y][last[y][x]] , i; double ret = dfs(t , y) / (d[y] + 1); for (i = head[y] ; i ; i = next[i]) ret += dfs(t , to[i]) / (d[y] + 1); return f[x][y] = ret + 1; } int main() { int n , m , p1 , p2 , x , y , i; scanf ( "%d%d%d%d" , &n , &m , &p1 , &p2); for (i = 1 ; i <= m ; i ++ ) scanf ( "%d%d" , &x , &y) , add(x , y) , add(y , x); for (i = 1 ; i <= n ; i ++ ) bfs(i); printf ( "%.3lf\n" , dfs(p1 , p2)); return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术