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
  7 typedef std::vector<int> Vec;
  8 typedef Vec::iterator It;
  9
 10 const int maxN=1001;
 11 const double notVis=-1.0;
 12
 13 Vec adj[maxN];
 14 int N,E;
 15 int C,K;
 16 int moveTo[maxN][maxN];
 17
 18 void init()
 19 {
 20     for(int i=1;i<maxN;i++) adj[i].clear();
 21     memset(moveTo,0,sizeof(moveTo));
 22 }
 23
 24 bool input()
 25 {
 26     if(scanf("%d%d",&N,&E)==EOF) return false;
 27     init();
 28     scanf("%d%d",&C,&K);
 29     int v1,v2;
 30     for(int i=1;i<=E;i++)
 31     {
 32         scanf("%d%d",&v1,&v2);
 33         adj[v1].push_back(v2);
 34         adj[v2].push_back(v1);
 35     }
 36     return true;
 37 }
 38
 39 struct Node
 40 {
 41     int idx;
 42     int layer;
 43     Node(int i,int l):idx(i),layer(l) {}
 44     bool operator < (const Node& other) const
 45     {
 46         return this->layer > other.layer ||
 47             (this->layer == other.layer && this->idx > other.idx);
 48     }
 49 };
 50
 51 void calcMoveTo()
 52 {
 53     std::priority_queue<Node> pq;
 54     for(int t=1;t<=N;t++)
 55     {
 56         moveTo[t][t]=t;
 57         pq.push(Node(t,0));
 58         while(!pq.empty())
 59         {
 60             Node cur=pq.top();
 61             pq.pop();
 62             int& v=cur.idx;
 63             for(It x=adj[v].begin();x!=adj[v].end();++x)
 64                 if(!moveTo[*x][t])
 65                 {
 66                     moveTo[*x][t]=v;
 67                     pq.push(Node(*x,cur.layer+1));
 68                 }
 69         }
 70     }
 71 }
 72
 73 double dp[maxN][maxN];
 74
 75 double solve_aux(int Cpos,int Kpos)
 76 {
 77     if(dp[Cpos][Kpos]!=0.0)
 78         return dp[Cpos][Kpos];
 79     for(It x=adj[Kpos].begin();x!=adj[Kpos].end();++x)
 80     {
 81         if(Cpos==(*x)) continue;
 82         int Cnext=Cpos; bool ok=false;
 83         for(int i=1;i<=2 && !ok;i++)
 84         {
 85             Cnext=moveTo[Cnext][*x];
 86             if(Cnext==(*x))
 87             {
 88                 dp[Cpos][Kpos]+=1.0;
 89                 ok=true;
 90             }
 91         }
 92         if(!ok) dp[Cpos][Kpos]+=(1.0+solve_aux(Cnext,*x));
 93     }
 94     dp[Cpos][Kpos]/=double(adj[Kpos].size());
 95     return dp[Cpos][Kpos];
 96 }
 97
 98 double solve()
 99 {
100     if(C==K) return 0.0;
101     for(int i=1;i<=2;i++)
102     {
103         C=moveTo[C][K];
104         if(C==K) return 1.0;
105     }
106     memset(dp,0,sizeof(dp));
107     for(int i=1;i<=N;i++) adj[i].push_back(i);
108     return 1.0+solve_aux(C,K);
109 }
110
111 int main()
112 {
113     while(input())
114     {
115         calcMoveTo();
116         printf("%.3lf\n",solve());
117     }
118     return 0;
119 }
时间: 2024-11-05 13:15:55

Vijos1675 NOI2005 聪聪和可可 记忆化搜索的相关文章

【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之间有一条路. 所有的路都是无向的,即

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

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

【bzoj1415】[Noi2005]聪聪和可可 期望记忆化搜索

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

【BZOJ1415】【Noi2005】聪聪和可可 概率DP 记忆化搜索

链接: #include <stdio.h> int main() { puts("转载请注明出处[辗转山河弋流歌 by 空灰冰魂]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/46457811"); } 题解: 记忆化搜索. f(i,j) 表示猫在 i .鼠在 j 时的期望. 然后显然它是拓扑的,然后先枚举起点n遍bfs算出 f(i,j) 时猫只走一步应该到哪个节点,然后对于 f(i,j) 枚

HDU 1513 Palindrome:LCS(最长公共子序列)or 记忆化搜索

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1513 题意: 给你一个字符串s,你可以在s中的任意位置添加任意字符,问你将s变成一个回文串最少需要添加字符的个数. 题解1(LCS): 很神奇的做法. 先求s和s的反串的LCS,也就是原串中已经满足回文性质的字符个数. 然后要变成回文串的话,只需要为剩下的每个落单的字符,相应地插入一个和它相同的字符即可. 所以答案是:s.size()-LCS(s,rev(s)) 另外,求LCS时只会用到lcs[i-

uva 1076 - Password Suspects(AC自动机+记忆化搜索)

题目链接:uva 1076 - Password Suspects 题目大意:有一个长度为n的密码,存在m个子串,问说有多少种字符串满足,如果满足个数不大于42,按照字典序输出. 解题思路:根据子串构建AC自动机,然后记忆化搜索,dp[i][u][s]表示第i个字符,在u节点,匹配s个子串. #include <cstdio> #include <cstring> #include <queue> #include <string> #include <

poj 1579(动态规划初探之记忆化搜索)

Function Run Fun Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17843   Accepted: 9112 Description We all love recursion! Don't we? Consider a three-parameter recursive function w(a, b, c): if a <= 0 or b <= 0 or c <= 0, then w(a, b

记忆化搜索,FatMouse and Cheese

1.从gird[0][0]出发,每次的方向搜索一下,每次步数搜索一下 for(i=0; i<4; i++) { for(j=1; j<=k; j++) { int tx=x+d[i][0]*j; int ty=y+d[i][1]*j; if(tx>=0&&tx<n&&ty>=0&&ty<n&&grid[x][y]<grid[tx][ty]) { int temp=memSearch(tx,ty); i

LightOJ1417 Forwarding Emails(强连通分量+缩点+记忆化搜索)

题目大概是,每个人收到信息后会把信息发给他认识的一个人如此下去,问一开始要把信息发送给谁这样看到信息的人数最多. 首先找出图中的SCC并记录每个SCC里面的点数,如果传到一个SCC,那么里面的人都可以看到信息. 然后SCC缩点后就形成DAG,直接记忆化搜索,d(u)搜索从u点出发开始传最多能传多少人. 最后就是找答案了. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namesp