http://acm.hdu.edu.cn/showproblem.php?pid=4405
题意:在一个1×n的格子上掷色子,从0点出发,掷了多少前进几步,同时有些格点直接相连,即若a,b相连,当落到a点时直接飞向b点。求走到n或超出n期望掷色子次数
分析:简单的题目,拿来入门很不错:
如果没有飞机的线 ,这题就是直接 dp[i]+=dp[i+x]/6 +1 了 ; 当前的期望由子期望相加 ; 那航线怎么考虑呢?一开始我以为是加上可以走到点的dp[v] ,可是仔细推敲这是不对了,在注意到航线的转移是不需要价值的,所以直接dp[u]=dp[v] 就好;为什么呢?很简单,例如: 7->8 , 因为8是可以直接由7来的,那8就继承7的期望

#include<bits/stdc++.h> using namespace std; vector<int>G[100010]; bool vis[100010]; double dp[100010]; int main() { int n,m; while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break; for(int i=0 ; i<=n ; i++) G[i].clear(); for(int i=0 ; i<m ; i++) { int u,v;scanf("%d%d",&u,&v); G[v].push_back(u); } memset(dp,0,sizeof(dp)); memset(vis,0,sizeof(vis)); for(int i=0 ; i<G[n].size() ; i++) { int v=G[n][i]; dp[v]=0; vis[v]=1; } for(int i=n-1 ; i>=0 ; i--) { if(vis[i]==0){ for(int x=1 ; x<=6 ; x++) { dp[i]+=dp[i+x]/6.0; } dp[i]++;} for(int j=0 ; j<G[i].size() ; j++) { int v=G[i][j]; dp[v]=dp[i]; vis[v]=1; } } printf("%.4lf ",dp[0]); } }

#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; #define N 100010 double dp[N]; int nxt[N]; int main() { int n, m; while(~scanf("%d%d", &n, &m), n+m) { memset(nxt, -1, sizeof(nxt)); for(int i = 0; i < m; i++) { int u, v; scanf("%d%d", &u, &v); nxt[u] = v; } memset(dp, 0, sizeof(dp)); double dec = (double)1 / 6; for(int i = n - 1; i >= 0; i--) { if(nxt[i] != -1) { dp[i] = dp[nxt[i]]; //如果可以飞,就直接把上一步的值赋给它 continue; } for(int j = 1; j <= 6; j++) { if(i + j <= n) { dp[i] += dp[i + j] * dec; //不能飞的话,就掷骰子为1-6的概率都为1/6,递推 } } dp[i]++; //走到下一步要+1 } printf("%.4f ", dp[0]); } return 0; }