洛谷P4232 无意识之外的捉迷藏

题目背景

(五)心与心的对话

旧都还在下着雪。

不知道走了多远的路,已经远离街市了。

眼前隐隐约约能看到一座巨大的宫殿。

那就是,地灵殿吗?

心里突然紧张了起来。

这里住着旧地狱最可怕的觉妖怪。

古明地觉,她拥有读心的能力。人类,妖怪,甚至是怨灵,站在她面前的时候都如同赤身裸体,没有任何秘密可言。而且,听说在战斗中,她还会使用催眠术不断激起对手内心深处的恐怖回忆,从心灵上打垮对手。这样的妖怪自然会被人讨厌啦。

不过,此次地底之旅可不能因为要遇到可怕的妖怪而就此结束。

咚咚咚,敲了敲地灵殿的大门。

“来客吗,真是少见呢。”

眼前,站着一个少女,穿着蓝色的衣服,粉红色的裙子,头发也是粉红色的。

在她的胸前,悬着一只红色的大眼睛,通过眼睛周围的六根管子连接着身体。

她看起来很温柔的样子,完全不像听说的那样恐怖。

“来地底旅行的外面世界的人类吗?真是非常少见呢,居然找到了这里”

“看起来没有别的想法,就是想来转转呢,那就进来吧”

走进大门。

不愧是地灵”殿”,真的是好大的一个宫殿,桃红色和黑色相间的地板,印有花纹的窗户。

眼前是一组很宽的台阶,通向二楼,然后分成左右两个通道。

“很漂亮吧,这里空间大,宠物们都很喜欢呢。”

就这样,我跟着觉进入了她工作的房间,我们坐在沙发上聊了很久,虽然我很少说话。

在聊天的过程中,我了解到她还有一个妹妹古明地恋,由于不愿让别人因为自己会读心而讨厌自己,闭上了觉之瞳。觉为了开导妹妹,经常和宠物陪着她玩。

地灵殿,觉和妹妹,宠物们,一直在过着平静又温馨的生活。

“既然来这里了,就和我们一起玩吧。”觉邀请我们参与她们的游戏。

地底的妖怪会玩怎样的游戏呢?

于是,就这样,我就答应参与觉和恋的“无意识的捉迷藏”了。

说是”捉迷藏”,其实和普通的捉迷藏区别很大,更类似于”捉人游戏”。

就是觉和恋一开始分别站在两个地方,觉要捉到恋就算赢了。

但为什么又说是”捉迷藏”呢?

原来恋恋可以无意识地行动,也就是可以让周围人在潜意识里忽略她的存在,类似隐身,但又不是隐身。真是有趣的能力呢,是不是闭上了觉之瞳的缘故?

我们玩得很开心。有时无意识碰到了恋恋的手,还吓了一跳呢。

一段时间后,姐妹俩累了,觉还有工作要处理,就先回去了。

宠物们似乎意犹未尽,她们还想继续。

“可是在这个旧地狱啊,除了主人的妹妹恋以外,哪里又有妖怪能够操纵无意识呢?

算了,干脆玩普通的捉人游戏吧。”阿燐提议道。

于是宠物们很快又忘我地投入了”无意识之外的捉迷藏”中。

不知什么时候,我感到背后一凉,回过头一看,原来是恋恋。

我们就这样站在这里看着宠物们玩。

虽然不知道为什么能耐心地看那么长时间,但几个小时过去了,我们依然站在这里。

恋恋好像有一些疑问,在经过简单的交流后,我把她的疑问做了一个总结。

(见题目描述)

这个问题对无意识的恋恋来说果然无法解决啊。

能和姐妹俩聊得这么开心,真是很感激呢,那就尽自己的努力思考一下这个问题吧。

(后续剧情见题解,接下来请看T4)

题目描述

###问题摘要:

在一个有向无环图上,阿燐和阿空第0个时刻分别站在编号为𝑠𝑟sr​,𝑠𝑘sk​的节点,二人都知道双方的初始位置,对地图完全了解。

从第1个时刻起,每个时刻阿燐和阿空都可以选择站着不动,也可以选择移动到相邻的节点,二人每时刻的移动是同时开始的,并且不能中途改变方向。

阿燐被阿空捉住时,游戏立即结束。如果阿空一直没有捉住阿燐,第𝑡t个时刻结束后两人就不能再继续移动了,游戏将在第𝑡+1t+1个时刻结束。

阿空的目的是尽快捉住阿燐(捉住的定义是与阿燐同一时刻站在同一节点),而阿燐的目的是尽可能更长时间不被阿空捉住。具体而言,若一场游戏进行了𝑡0t0​时刻,阿燐的得分是𝑡0t0​,阿空的得分是−𝑡0−t0​,双方都希望自己得分(或得分的期望值)更高。

我们认为在这个过程中阿燐和阿空随时都能知道对方的位置。两人在第𝑡t个时刻不能看出第𝑡+1t+1个时刻对方要走到哪里。

恋恋想知道,在双方最优决策的情况下,游戏结束时刻的期望值是多少。

输入格式

第一行5个整数𝑛n,𝑚m,𝑠𝑟sr​,𝑠𝑘sk​,𝑡t,用空格隔开,下同。

𝑛n表示地图点数,𝑚m表示边数。

接下来𝑚m行,每行两个整数𝑎a,𝑏b,表示从𝑎a到𝑏b有一条单向边(不存在重边)。

输出格式

一个实数,四舍五入保留3位小数,表示游戏结束时刻的期望值。

你的答案必须和标准答案完全相同才算正确。

输入输出样例

输入 #1

3 2 1 2 10
1 3
2 3

输出 #1

11.000

输入 #2

6 8 2 1 2
1 2
1 3
1 5
2 3
3 5
5 6
6 4
2 4

输出 #2

2.333

说明/提示

###样例解释:

样例1:阿燐只要一直不动,阿空在前𝑡t单位时间内就无法抓到阿燐,答案为𝑡+1t+1,即11.000

样例2:无可奉告

###数据范围:

对于30%的数据 𝑛⩽3n⩽3,捆绑测试

对于100%的数据 𝑛,𝑡⩽20n,t⩽20,前40%的数据和后30%的数据分别捆绑测试

###提示: 本题主要考察你能否使用正确的方法算出答案,对算法运行耗时要求不高。

by orangebird

Code:

#include<bits/stdc++.h>
using namespace std;

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || '9'<ch){if(ch=='-')f=-1;ch=getchar();}
    while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar();
    return x*f;
}

typedef double db;
const int N=29;
const int M=29;
const db eps=1e-8;
const db Inf=19260817;

db a[M][M];
namespace simplex
{
    int n,m;
    int id[N+M];

    inline void pivot(int x,int y)
    {
        swap(id[y],id[n+x]);
        db t=a[x][y];
        a[x][y]=1.0;

        for(int i=0;i<=n;i++)
            a[x][i]/=t;
        for(int i=0;i<=m;i++)
            if(i!=x)
            {
                t=a[i][y];
                a[i][y]=0;
                for(int j=0;j<=n;j++)
                    a[i][j]-=t*a[x][j];
            }
    }

    inline bool init()
    {
        while(1)
        {
            db k=-eps;
            int l=0,e=0;

            for(int i=1;i<=m;i++)
                if(a[i][0]<k)
                    k=a[i][0],l=i;
            if(!l)return 1;
            for(int i=1;i<=n && !e;i++)
                if(a[l][i]<-eps)
                    e=i;
            if(!e)return 0;
            pivot(l,e);
        }
    }

    inline bool simplex()
    {
        while(1)
        {
            db k=1e18;
            int l=0,e=0;

            for(int i=1;i<=n && !e;i++)
                if(a[0][i]>eps)
                    e=i;
            if(!e)return 1;
            for(int i=1;i<=m;i++)
                if(a[i][e]>eps && a[i][0]/a[i][e]<k)
                    k=a[i][0]/a[i][e],l=i;
            if(!l)return 0;
            pivot(l,e);
        }
    }

    inline db mina()
    {
        if(!init())exit(0);
        if(!simplex())exit(0);
        return -a[0][0];
    }

    inline void init(int x,int y)
    {
        n=x;m=y;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                a[i][j]=0.0;
        for(int i=1;i<=n;i++)
            id[i]=i;
        for(int i=1;i<=m;i++)
            id[n+i]=0;
    }
}

int n,m,sr,sk,t;
vector<int> g[N];
db f[N][N][N];
int deg[N];

inline void add(int u,int v)
{
    g[u].push_back(v);
    deg[u]++;
}

inline void dfs(int x,int y,int tim)
{
    if(tim==t+1 || x==y){f[x][y][tim]=0;return;}
    if(f[x][y][tim]!=-Inf)return;

    for(int i=0;i<g[x].size();i++)
        for(int j=0;j<g[y].size();j++)
            dfs(g[x][i],g[y][j],tim+1);

    simplex::init(deg[y],deg[x]);
    for(int i=0;i<g[x].size();i++)
    {
        for(int j=0;j<g[y].size();j++)
            a[i+1][j+1]=f[g[x][i]][g[y][j]][tim+1]+1.0;
        a[i+1][0]=1;
    }

    a[0][0]=0;
    for(int i=1;i<=deg[y];i++)
        a[0][i]=1;

    f[x][y][tim]=1.0/simplex::mina();
}

int main()
{
    n=read();m=read();
    sr=read();sk=read();
    t=read();
    for(int i=1,u;i<=m;i++)
        u=read(),add(u,read());
    for(int i=1;i<=n;i++)
        add(i,i);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int k=0;k<=t;k++)
                f[i][j][k]=-Inf;

    dfs(sr,sk,0);
    printf("%.3lf\n",f[sr][sk][0]);
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值