bzoj 1415 聪聪和可可(概率DP)
来源:互联网 发布:弹弓专卖店淘宝网 编辑:程序博客网 时间:2024/05/01 16:09
1415: [Noi2005]聪聪和可可
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 475 Solved: 279
[Submit][Status]
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
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
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。
Source
此题为研究概率DP的第一题。由于前几天被水概率DP虐了。所以开始刷概率DP了。
思路:
题目要求聪聪要不断向可可靠近。且走保证标号尽量小。那么我们可以用SPFA预处理出pos[i][j]。
pos[i][j]表示表示顶点i到顶点j的最短路上与顶点i相邻且编号最小的顶点编号。
即聪聪在景点i,可可在景点j时,聪聪第1步会走到的景点编号
此处感谢小吉吉对SPFA的讲解!
dp[i][j]表示来表示聪聪在顶点i,可可在顶点j时聪聪抓住可可的平均步数。
令w[i, j]表示与顶点i相邻的j个点编号,而用t[i]表示顶点i的度。
可以确定聪聪下一步所在的顶点即pos[pos[i, j], j],可可下一步在顶点w[i, j],概
率为1/(t[i]+1),下一步这个情况下的期望dp[pos[pos[i, j], j], w[i, j]]已经计算出,那么就
是比dp[pos[pos[i, j], j], w[i, j]]多出一步。可可在原地停留的情况则类似。
所以可以得到:
dp[i][j]=(segma(dp[pos[pos[i][j]][j][w[j][k]])+dp[pos[pos[i][j]][j]][j])/(t[i]+1)。
是比dp[pos[pos[i, j], j], w[i, j]]多出一步。可可在原地停留的情况则类似。
所以可以得到:
dp[i][j]=(segma(dp[pos[pos[i][j]][j][w[j][k]])+dp[pos[pos[i][j]][j]][j])/(t[i]+1)。
i=j时
当然dp[i, i] = 0,因为聪聪和可可已经在同一个点。
当然dp[i, i] = 0,因为聪聪和可可已经在同一个点。
若pos[pos[i, j], j] = j 或pos[i, j]= j 则说明在这一步聪聪即可吃掉可可,那么dp [i, j]=1。
用记忆化搜索即可解决。
用记忆化搜索即可解决。
详细见代码:
#include<stdio.h>#include<string.h>#include<iostream>#include<queue>using namespace std;const int maxn=1010;struct node//边结构{ int v; int cost; node *next;} edge[maxn<<1],*head[maxn];int ptr,pos[maxn][maxn],vis[maxn],dist[maxn];int n,e,sx,ex;double dp[maxn][maxn];queue<int> q;void adde(int u,int v){ edge[ptr].v=v; edge[ptr].next=head[u]; edge[ptr].cost=1; head[u]=&edge[ptr++];}void spfa(int s)//算最短路并得到pos[i][j]{ int u,v; node *p; while(!q.empty()) q.pop(); memset(vis,0,sizeof vis); memset(dist,0x3f,sizeof dist); dist[s]=0; for(p=head[s];p!=NULL;p=p->next)//先预处理起点周围的点 { v=p->v; pos[s][v]=v; q.push(v); dist[v]=1; vis[v]=1; } while(!q.empty()) { u=q.front(); vis[u]=0; q.pop(); for(p=head[u];p!=NULL;p=p->next) { v=p->v; if(dist[u]+p->cost<dist[v]) { dist[v]=dist[u]+p->cost; pos[s][v]=pos[s][u];//更新最优决策点 if(!vis[v]) { q.push(v); vis[v]=1; } } else if(dist[u]+p->cost==dist[v]&&pos[s][u]<pos[s][v]) { pos[s][v]=pos[s][u]; if(!vis[v]) { q.push(v); vis[v]=1; } } } }}void dfs(int u,int v)//计算聪聪在u可可在v。聪聪吃到可可的步数的期望。记忆化搜索{ if(dp[u][v]>=0) return ; int np,cnt=0; double sum=0; node *p; np=pos[pos[u][v]][v]; if(np==v) { dp[u][v]=1; return; } for(p=head[v];p!=NULL;p=p->next) { dfs(np,p->v); sum+=dp[np][p->v]; cnt++;//统计边数 } dfs(np,v); sum+=dp[np][v];//加上可可不动的期望 dp[u][v]=sum/(cnt+1)+1;//走了一步了所以加1}int main(){ int i,j,a,b; while(~scanf("%d%d",&n,&e)) { scanf("%d%d",&sx,&ex); ptr=0; memset(head,0,sizeof head); for(i=1;i<=n;i++) for(j=1;j<=n;j++) dp[i][j]=-1; for(i=0;i<e;i++) { scanf("%d%d",&a,&b); adde(a,b); adde(b,a); } for(i=1;i<=n;i++) { dp[i][i]=0;//相遇直接吃掉步数为0 pos[i][i]=i; spfa(i); } dfs(sx,ex); printf("%.3lf\n",dp[sx][ex]); } return 0;}
- bzoj 1415 聪聪和可可(概率DP)
- BZOJ 1415: [Noi2005]聪聪和可可|概率dp
- BZOJ 1415 [Noi2005]聪聪和可可【概率dp】
- bzoj 1415 [Noi2005]聪聪和可可 概率dp
- [BZOJ 1415][NOI 2005]聪聪和可可(SPFA+概率DP)
- BZOJ 1415: [Noi2005]聪聪和可可 概率DP,记忆化搜索,BFS
- BZOJ 1415: [Noi2005]聪聪和可可 期望dp
- BZOJ 1415聪聪和可可 期望dp
- bzoj 1415 聪聪和可可 (期望dp)
- BZOJ 1415|NOI 2005|聪聪和可可|概率期望|动态规划
- bzoj 1415: [Noi2005]聪聪和可可 (概率与期望)
- 【BZOJ 1415】 [Noi2005]聪聪和可可
- BZOJ 1415: [Noi2005]聪聪和可可
- bzoj 1415 聪聪和可可 【期望】
- 1415: [Noi2005]聪聪和可可(BFS+SPFA+概率DP)
- 【BZOJ】【P1415】【Noi2005】【聪聪和可可】【题解】【期望DP】
- BZOJ 2152: 聪聪可可【树形dp
- 【BZOJ1415】【Noi2005】聪聪和可可 概率DP 记忆化搜索
- Java 中 HashMap 的工作机制
- 大话设计模式之中介者模式
- Android安装eclipse报错处理(备忘)
- 分支预测
- Linux 创建文件、文件夹及查看文件内容
- bzoj 1415 聪聪和可可(概率DP)
- IOS各类错误汇总
- 图解数据结构(1)——大圈表示法、动态数组和单向链表
- 类的设计技巧
- java中的static详解
- bullet 物理引擎的角色控制器(character controller)
- hdu(3007)
- The Boost C++ Libraries
- java初始化顺序