NOI2005 : 聪聪和可可

传送门:

/*
    bzoj : 1415
    Noi: 2005 聪聪和可可
    Solution : 概率好像还是挺头疼的。
    但是大多数算期望都是用dp来算的。
    不会算期望只是证明你dp不好,而不是你概率不好,说白了就是自己不会。 
    设f[x][y]表示x - > y的期望步数,p[x][y]为x - > y的最短路中的标号最小的序号。
    显然猫走两步老鼠走一步,DAG。
    f[x][y] = {[\sigma dfs(p[p[x][y]][y],V)] / Size[V]} + 1;V = {v | dis[v][y] <= 1;}
    翻译成人话就是x - > y的期望步数为:xy走两步后y随机走一步(或者不走)的期望步数之和 / y的选择数 + 1; 
    记忆化搜索即可. 
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#define Rep(i,n) for(int i = 1; i <= n ; i ++)
#define RepG(i,x) for(int i = head[x] ;~ i ; i = edge[i].next)
#define CLR(a,b) memset(a,b,sizeof(a))
#define v edge[i].to
using namespace std;
const int inf = 1 << 30;
typedef long long ll;
int read(){
    char ch = getchar();
    while((ch < '0' || ch > '9') && ch != '-')ch = getchar ();
    int x = 0;
    bool flag = 0;
    if(ch == '-')ch = getchar(),flag = 1;
    while(ch >= '0' && ch <= '9')x = (x << 1) + (x << 3) + ch - '0',ch = getchar ();
    return flag ? -x : x;
}
const int N = 1005;
double f[N][N];
int dis[N][N],p[N][N];
int cnt = 0 ,head[N];
void Init(){
    CLR(head,-1);
    cnt = 0;
}
struct Edge{int next,to;}edge[N << 1];
int n,m,S,T;
void save(int a,int b){
    edge[cnt] = (Edge){head[a],b},head[a] = cnt ++;
    a ^= b,b ^= a,a ^= b;
    edge[cnt] = (Edge){head[a],b},head[a] = cnt ++;
}
double dfs(int x,int y)
{
    if(f[x][y])return f[x][y];
    if(x == y)return 0;
    if(p[x][y] == y || p[p[x][y]][y] == y)return f[x][y] = 1;
    double tot = dfs(p[p[x][y]][y],y),tp = 0;
    RepG(i,y){
        tot += dfs(p[p[x][y]][y],v);
        tp ++;
    }
    return f[x][y] = tot / (tp + 1) + 1;
}
int q[N];
void bfs(int s){
    int h = 0,t = 1;
    q[0] = s,dis[s][s] = 0;
    while(h != t)
    {
        int x = q[h ++],tmp = p[s][x];
        if(h == 1001)h = 0;
        RepG(i,x)
            if(dis[s][v] == -1 || (dis[s][x] + 1 == dis[s][v] && tmp < p[s][v]))
            {
                dis[s][v] = dis[s][x] + 1;
                p[s][v] = tmp;
                if(!tmp)p[s][v] = v;
                q[t ++] = v;
                if(t == 1001)t = 0;
            }
    }
}
int main (){
    Init();
    CLR(dis,-1);
    n = read(),m = read();
    S = read(),T = read();
    Rep(i,m)
    {
        int a,b;
        a = read(),b = read();
        save(a,b);
    }
    Rep(i,n)bfs(i);
    printf("%.3f\n",dfs(S,T));
    return 0;
}

发现自己还是太弱了,其实这题的状态什么的真的是很显然的。
『我绝对不会告诉你们我的代码是看了hzwer的之后才写的』

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值