Educational Codeforces Round 138 (Rated for Div. 2) E (01BFS)

Educational Codeforces Round 138 (Rated for Div. 2) E (01BFS)

题意: 给定一个 n ∗ m n*m nm 的田地,让我们构造仙人掌墙,使得玩家不能从第 1 1 1 行,走到第 n n n 行。仙人掌墙需满足以下条件:1、任意两个仙人掌不可相邻。2、构造完的仙人掌墙可以阻断玩家从第 1 1 1 行走到第 n n n 行。并且田地中已有存在的初始仙人掌,我们不可删除,初始情况也同样满足任意两个仙人掌不相邻。我们需要在初始已有的仙人掌前提下增加尽可能少的仙人掌,构建仙人掌墙,问我们增加最少的仙人掌数量的情况下最终的田地形状,或者声明无法构建仙人掌墙,输出 NO

思路: 首先考虑,倘若田地中不存在仙人掌,那么我们的最优方案是为什么?由于仙人掌不可以相邻放置,那么最优情况就是将所有仙人掌对角放置,且恰好放置 m m m 个,对应 1 − m 1-m 1m 列,每列一个,且每相邻两列的仙人掌放置行坐标的绝对值不可超过 1 1 1 。一定可以保证该情况下,新添的仙人掌数量是最少的。如下图所示:

........
.......#
......#.
.....#..
....#...
...#....
#.#.....
.#......

,但在已有初始仙人掌存在的前提下,我们又该如何放置呢?我们可以从每 1 1 1 行的第 1 1 1 的下标跑短路,例如从第 1 1 1 行开始,那么我们最终的目标就是 ( 1 , 0 ) (1,0) (1,0) ⟹ \Longrightarrow ( ? , m − 1 ) (?,m-1) (?,m1) 该类短路由于边权仅为 0 0 0 1 1 1 ,因此我们可以直接使用 01 01 01 d e q u e deque deque 来跑短路,且时间复杂度更优。最终跑完短路之后枚举 ( 0 (0 (0 ~ ( n − 1 ) , m − 1 ) (n-1),m-1) (n1),m1),找到最小增加仙人掌代价即可。然后逆向恢复,将最短路径上的所有 . . . 变成 # 即可,用一个 p r e < p a i r < i n t , i n t > > pre<pair<int,int>> pre<pair<int,int>> 来记录即可。需要注意本题由于只保证 n ∗ m < = 4 e 5 n*m<=4e5 nm<=4e5,因此直接开静态数组会 m l e mle mle ,因此采用动态数组 v e c t o r vector vector 来开二维数组,且初始化所有点的距离为 INF

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#pragma GCC optimize(3)
typedef pair<int,int>PII;
#define pf push_front
#define pb push_back
const int INF = 2e18;
int dx[]={-1,-1,1,1};
int dy[]={-1,1,1,-1};
void cf(){
    int n,m;
    cin>>n>>m;
    vector<string>s(n);
    vector<vector<int>> dist(n,vector<int>(m,INF));
    vector<vector<PII>> pre(n,vector<PII>(m));
    for(int i=0;i<n;i++){
        cin>>s[i];
    }
    auto check=[&](int a,int b){
        if(a<0||a>n-1||b<0||b>m-1)return false;
        if(a>0&&s[a-1][b]=='#')return false;
        if(a<n-1&&s[a+1][b]=='#')return false;
        if(b>0&&s[a][b-1]=='#')return false;
        if(b<m-1&&s[a][b+1]=='#')return false;
        return true;
    };
    deque<PII>q;
    for(int i=0;i<n;i++){
        if(check(i,0)){
            if(s[i][0]=='#'){
                dist[i][0]=0;
                q.pf({i,0});
            }
            else{
                dist[i][0]=1;
                q.pb({i,0});
            }
        }
    }
    while(q.size()){
        auto [a,b]=q.front();
        q.pop_front();
        for(int i=0;i<4;i++){
            int x=a+dx[i];
            int y=b+dy[i];
            if(check(x,y)){
                if(dist[a][b]+(s[x][y]!='#')<dist[x][y]){
                    dist[x][y]=dist[a][b]+(s[x][y]!='#');
                    pre[x][y]={a,b};
                    if(s[x][y]=='#')q.pf({x,y});
                    else q.pb({x,y});
                }
            }
        }
    }
    int ans=INF;
    int local=-1;
    for(int i=0;i<n;i++){
        if(dist[i][m-1]<ans){
            ans=dist[i][m-1];
            local=i;
        }
    }
    if(local==-1){
        cout<<"NO"<<endl;
        return;
    }
    else{
        cout<<"YES"<<endl;
        int nowx=local;
        int nowy=m-1;
        while(1){
            s[nowx][nowy]='#';
            if(nowy==0)break;
            auto [a,b] = pre[nowx][nowy];
            nowx=a;
            nowy=b;
        }
    }
    for(int i=0;i<n;i++){
        cout<<s[i]<<endl;
    }
}   
signed main(){
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    int _=1;
    cin>>_;
    while(_--){
        cf();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值