算法竞赛入门经典 每日一题(wyh的吃鸡)

该博客讨论了一种简化版的吃鸡游戏场景,其中玩家需从起点S出发,在限定时间内到达唯一的安全区域X。地图由不同符号表示,包括空地、障碍物和车。算法采用BFS寻找最短路径,考虑有车和无车两种情况下的移动速度。博客给出了输入输出示例,并展示了算法实现。

题目描述 

最近吃鸡游戏非常火,你们wyh学长也在玩这款游戏,这款游戏有一个非常重要的过程,就是要跑到安全区内,否则就会中毒持续消耗血量,我们这个问题简化如下 

假设地图为n*n的一个图,图中有且仅有一块X的联通快代表安全区域,有一个起点S代表缩圈的时候的起点,图中C代表的是车(保证车的数量小于等于100),标记为.的代表空地,可以任意通过,O代表障碍物不能通过。每次没有车的时候2s可以走一个格(只能走自己的上下左右4个方向),有车的话时间为1s走一个格 

现在告诉你最多能坚持的时间为t秒,问你在t秒内(含t秒)能否从s点到达安全区域,能的话输出YES,并且输出最短时间,不能的话输出NO 

输入描述:

输入第一行一个整数T(1<=T<=10)
接下来有T组测试数据,每组测试数据输入2个数n和k(1<=n<=100,1<=k<=10^9)
接下来n行,每行n个字符,代表对应的n*n的地图,每个字符都是上面的一种,并且保证只有一个起点,只有一块安全区域。

输出描述:

对于每组测试数据,先输出能否到达,能的话输出YES,然后换行输出最短时间,如果不能的话直接输出NO

示例1

输入

复制

3
2 3
.X
S.
2 3
.X
SC
2 4
.X
S.

输出

复制

NO
YES
3
YES
4

要注意:

X可能不只是一块 有可能是一片区域

所以要枚举X的区域

要用到最短路 bfs实现

const int MAX=10010;
int dis[MAX][MAX][2];
int vis[MAX][MAX][2];
char s[MAX][MAX];
int x[MAX];
int y[MAX];
int sx,sy;
int z;
int t;
int ans;
int n,k;
struct node {
    int x,y,z;
};
int check(int x,int y){
    if(x<1||x>n||y<1||y>n||s[x][y]=='O') return 1;
    return 0;
}
void bfs(int x,int y){
    queue<node> qu;
    qu.push({x,y,0});
    dis[x][y][0]=0;
    vis[x][y][0]=1;
    node p,q;
    while (!qu.empty()) {
        node q=qu.front();
        qu.pop();
        vis[q.x][q.y][q.z]=0;
        for(int i=0;i<4;i++){
            p.x=q.x+xd[i];
            p.y=q.y+yd[i];
            p.z=q.z;
            if(check(p.x,p.y)) continue;
            int c;
            if(s[p.x][p.y]=='C') p.z=1;
            if(q.z==1) c=1;
            else c=2;
            if(dis[p.x][p.y][p.z]>dis[q.x][q.y][q.z]+c){
                dis[p.x][p.y][p.z]=dis[q.x][q.y][q.z]+c;
                if(!vis[p.x][p.y][p.z]){
                    vis[p.x][p.y][p.z]=1;
                    qu.push(p);
                }
            }
        }
    }
}
int main(){
    cin>>t;
    while (t--) {
        
        cin>>n>>k;
        mms(dis,INF);
        mms(vis,0);
        z=0;
        for(int i=1;i<=n;i++)
            cin>>s[i];
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(s[i][j]=='S'){
                    sx=i;
                    sy=j;
                }
                if(s[i][j]=='X'){
                    x[z]=i;
                    x[z++]=j;
                }
            }
        }
        ans=INF;
        bfs(sx,sy);
        for(int i=0;i<z;i++){
            ans=min(ans,dis[x[i]][y[i]][0]);
            ans=min(ans,dis[x[i]][y[i]][1]);
        }
        if(ans>k) cout<<"NO"<<endl;
        else {
            cout<<"YES"<<endl;
            cout<<ans;
        }
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭晋龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值