• 2023NOIP A层联测17-爆炸


    题目

    当一个炸弹以一个方向被引爆时,被触发的炸弹引爆方向是相反的。显然这是最佳的

    考虑对每个炸弹的上下左右离它最近的炸弹连边。这样就形成了若干个连通块,互不影响,可以分别计算答案。

    若一个连通块内有环,那么任意引爆其中一个炸弹,整个连通块的炸弹都会被引爆,得到连通块涉及的行列的水晶。

    若没有环,就可以选择一个只有左右/上下有炸弹的炸弹,将其引爆,这样可以把连通块内所有炸弹引爆,对比上一个情况的水晶,容易发现少了某一列/行的水晶(建议自己手模一下),减去即可。

    时间复杂度 O ( n m ) O(nm) O(nm)

    具体实现看代码

    #include
    using namespace std;
    const int N=3001,NN=9000001;
    int n,m,num1,num2,ans,vis[NN],dfn[NN],low[NN],num,fl,d[NN];
    char a[N][N];
    int head[NN],nxt[NN<<2],to[NN<<2],cnt,w[NN<<2];
    vector<int> v1,v2,v3;
    unordered_map<int,int> m1,m2; 
    void add(int u,int v,int W)
    {
        to[++cnt]=v;
        w[cnt]=W;
        nxt[cnt]=head[u];
        head[u]=cnt;
    }
    int ID(int x,int y){return (x-1)*m+y;}
    pair<int,int> DI(int x){return make_pair((x-1)/m+1,(x-1)%m+1);}
    void dfs(int u,int fa)
    {
        v3.push_back(u);
        auto czn=DI(u);
        vis[u]=1;
        if(!m1.count(czn.first)) m1[czn.first]=1,v1.push_back(czn.first);
        if(!m2.count(czn.second)) m2[czn.second]=1,v2.push_back(czn.second);
        for(int i=head[u];i;i=nxt[i]){
            if(to[i]!=fa){
                if(vis[to[i]]){fl=1;continue;}
                dfs(to[i],u);
            }
        }
    }
    bool check(int x)
    {
        int x1=0,x2=0;
        for(int i=head[x];i;i=nxt[i]){
            if(w[i]) x1=1;
            else x2=1;
        }
        return x1^x2;
    }
    int main()
    {
        freopen("boom.in","r",stdin);
        freopen("boom.out","w",stdout);
        scanf("%d%d%d%d",&n,&m,&num1,&num2);
        for(int i=1;i<=n;i++) scanf("%s",a[i]+1);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(a[i][j]!='b') continue;
                int x=i+1,y=j;
                while(x<=n&&a[x][y]!='b') x++;
                if(x<=n){
                    add(ID(i,j),ID(x,y),1),add(ID(x,y),ID(i,j),1);
                    d[ID(i,j)]++,d[ID(x,y)]++;
                }
                x=i,y=j+1;
                while(y<=m&&a[x][y]!='b') y++;
                if(y<=m){
                    add(ID(i,j),ID(x,y),0),add(ID(x,y),ID(i,j),0);
                    d[ID(i,j)]++,d[ID(x,y)]++;
                }
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(!vis[ID(i,j)]&&a[i][j]=='b'){
                    fl=0;
                    v1.clear(),v2.clear(),v3.clear();
                    m1.clear(),m2.clear();
                    dfs(ID(i,j),0);
                    sort(v1.begin(),v1.end());
                    sort(v2.begin(),v2.end());
                    int sum=0;
                    for(auto i:v1) for(int j=1;j<=m;j++) sum+=(a[i][j]=='k');
                    for(int i=1;i<=n;i++) for(auto j:v2) sum+=(a[i][j]=='k');
                    for(auto i:v1) for(auto j:v2) sum-=(a[i][j]=='k');
                    if(fl){
                        ans=max(ans,sum);
                    }
                    else{
                        for(auto i:v3){
                            if(check(i)){
                                auto czn=DI(i);
                                int x=sum;
                                if(w[head[i]]){
                                    for(int j=1;j<=m;j++) x-=(a[czn.first][j]=='k');
                                    for(auto j:v2) x+=(a[czn.first][j]=='k');
                                }
                                else{
                                    for(int i=1;i<=n;i++) x-=(a[i][czn.second]=='k');
                                    for(auto i:v1) x+=(a[i][czn.second]=='k');
                                }
                                ans=max(ans,x);
                            }
                        }
                        if(d[ID(i,j)]==0){
                            auto czn=DI(ID(i,j));
                            int x=sum;
                            for(int j=1;j<=m;j++) x-=(a[czn.first][j]=='k');
                            for(auto j:v2) x+=(a[czn.first][j]=='k');
                            ans=max(ans,x);
                            x=sum;
                            for(int i=1;i<=n;i++) x-=(a[i][czn.second]=='k');
                            for(auto i:v1) x+=(a[i][czn.second]=='k');
                            ans=max(ans,x);
                        }
                    }
                }
            }
        }
        cout<<ans;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
  • 相关阅读:
    计算机网络(第六弹) --- 与 HTTP 有关的八个问题
    FPGA之旅设计99例之第三例-----UART串口通信
    Linux--初识和几个简单的指令(1)
    codeforces每日5题(均1600)-第三十三天
    Jmeter的应用
    SpringBoot对接OpenAI
    关于【软件测试-自动化测试之面试技巧和注意事项】——侃侃而谈
    【Leetcode】 131. 分割回文串
    Rasa 多轮对话机器人
    Redis 集群详解及搭建过程
  • 原文地址:https://blog.csdn.net/dygxczn/article/details/134021738