noi.ac #529 神树的矩阵

题目链接:戳我

当 \(max(n, m) \ge 3\) 时,可以如下构造:
考虑下面这样三个矩阵,红 + 蓝 ? 绿得到的矩阵是一个第一行和最后一行全是 1,其他地方全是 0 的矩阵。
那么如果需要把中间某个位置变成 1,可以在红或蓝矩阵中的对应位置加一个 1。
如果需要把第一行或最后一行某个位置变成 0,可以在绿矩阵中的对应位置加一个 1。
(图床挂了......等回来我再放图片QAQ)
然后对于其他情况分别特判就行了(具体哪些可以看main函数)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#define MAXN 510
#define mp make_pair
using namespace std;
int n,m;
int move_x[4]={0,0,1,-1},move_y[4]={1,-1,0,0};
char s[MAXN][MAXN];
namespace subtask_0
{
    inline bool check()
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(s[i][j]=='1')
                    return false;
        return true;
    }
}
namespace subtask_1
{
    int done[MAXN][MAXN];
    inline bool bfs(int x,int y)//不带done的清空操作
    {
        queue<pair<int,int> >q;
        q.push(mp(x,y));
        while(!q.empty())
        {
            int u_x=q.front().first;
            int u_y=q.front().second;
            q.pop();
            done[u_x][u_y]=1;
            for(int k=0;k<=3;k++)
            {
                int xx=u_x+move_x[k];
                int yy=u_y+move_y[k];
                if(xx<1||xx>n||yy<1||yy>m||s[xx][yy]=='0'||done[xx][yy]) continue;
                done[xx][yy]=1;
                q.push(mp(xx,yy));
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(s[i][j]=='1'&&done[i][j]==0) return false;
        return true;
    }
    inline bool check()
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(s[i][j]=='1')
                {
                    if(bfs(i,j)==true) return true;
                    else return false;
                }
    }
    inline void solve()
    {
        printf("1\n+\n");
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                printf("%c",s[i][j]);
            puts("");
        }
    }
}
namespace subtask_2
{
    int cnt,cur_ans,pos;
    int fa[MAXN*MAXN],id[MAXN][MAXN];
    map<int,int>ex;
    set<int>sset[MAXN*MAXN];
    inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline bool check()
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                id[i][j]=++cnt,fa[cnt]=cnt;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                for(int k=0;k<=3;k++)
                    {
                        int xx=i+move_x[k];
                        int yy=j+move_y[k];
                        if(xx<1||xx>n||yy<1||yy>m||s[i][j]!=s[xx][yy]) continue;
                        int t=find(id[i][j]),tt=find(id[xx][yy]);
                        if(t!=tt) fa[t]=tt;
                    }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(s[i][j]=='0') continue;
                int t=find(id[i][j]);
                if(!ex.count(t)) ex[t]=1,cur_ans++;
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(s[i][j]=='0')
                    for(int k=0;k<=3;k++)
                    {
                        int xx=i+move_x[k];
                        int yy=j+move_y[k];
                        if(xx<1||xx>n||yy<1||yy>m||s[xx][yy]=='0') continue;
                        int t=find(id[i][j]),tt=find(id[xx][yy]);
                        sset[t].insert(tt);
                    }
            }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                if(s[i][j]=='0')
                {
                    int t=find(id[i][j]);
                    if((int)sset[t].size()==cur_ans)
                    {
                        pos=t;
                        break;
                    }
                }
            if(pos!=0) break;
        }
        if(pos==0) return false;
        return true;
    }
    inline void solve()
    {
        printf("2\n+\n");
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(s[i][j]=='1'||(s[i][j]=='0'&&find(id[i][j])==pos)) printf("1");
                else printf("0");
            }
            puts("");
        }
        printf("-\n");
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(s[i][j]=='0'&&find(id[i][j])==pos) printf("1");
                else printf("0");
            }
            puts("");
        }
    }
}
inline void solve_n_1()
{
    vector<pair<int,int> >vec;
    int now=1;
    while(now<=m)
    {
        int cnt1,cnt2;
        while(now<=m&&s[1][now]=='0') now++;
        if(now<=m&&s[1][now]=='1')
        {
            cnt1=now;
            while(now<=m&&s[1][now]=='1') now++;
            cnt2=now-1;
            vec.push_back(mp(cnt1,cnt2));
        }
    }
    printf("%d\n",(int)vec.size());
    for(int i=0;i<vec.size();i++)
    {
        printf("+\n");
        for(int j=1;j<=m;j++)
        {
            if(vec[i].first<=j&&j<=vec[i].second) printf("1");
            else printf("0");
        }
        puts("");
    }
}
inline void solve_m_1()
{
    vector<pair<int,int> >vec;
    int now=1;
    while(now<=n)
    {
        int cnt1,cnt2;
        while(now<=n&&s[now][1]=='0') now++;
        if(now<=n&&s[now][1]=='1')
        {
            cnt1=now;
            while(now<=n&&s[now][1]=='1') now++;
            cnt2=now-1;
            vec.push_back(mp(cnt1,cnt2));
            // printf("[%d %d]\n",cnt1,cnt2);
        }
    }
    printf("%d\n",(int)vec.size());
    for(int i=0;i<vec.size();i++)
    {
        printf("+\n");
        for(int j=1;j<=n;j++)
        {
            if(vec[i].first<=j&&j<=vec[i].second) printf("1\n");
            else printf("0\n");
        }
        // puts("");
    }
}
namespace others
{
    char t[MAXN][MAXN],r[MAXN][MAXN],q[MAXN][MAXN];
    inline void print()
    {
        printf("3\n");
        printf("+\n");
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                printf("%c",t[i][j]);
            puts("");
        }
        printf("+\n");
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                printf("%c",r[i][j]);
            puts("");
        }
        printf("-\n");
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                printf("%c",q[i][j]);
            puts("");
        }
    }
    inline void solve_m_2()
    {
        for(int i=1;i<=n;i++)
        {
            t[i][1]='1';
            t[i][2]=(s[i][2]=='1'?'1':'0');
        }
        for(int i=1;i<=n;i++)
        {
            r[i][2]='1';
            r[i][1]=(s[i][1]=='1'?'1':'0');
        }
        for(int i=1;i<=n;i++) q[i][1]=q[i][2]='1';
        print();
    }
    inline void solve()
    {
        for(int i=1;i<=n;i++)
        {
            t[i][1]='1',t[i][m]='0';
            r[i][1]='0',r[i][m]='1';
            for(int j=2;j<m;j++) t[i][j]=r[i][j]=s[i][j];
            if(i&1)
                for(int j=1;j<m;j++) t[i][j]='1';
            else
                for(int j=2;j<=m;j++) r[i][j]='1';
        }
        for(int i=1;i<=n;i++)
        {
            q[i][1]=(s[i][1]=='0'?'1':'0');
            q[i][m]=(s[i][m]=='0'?'1':'0');
            for(int j=2;j<m;j++) q[i][j]='1';
        }
        print();
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("ce.in","r",stdin);
    // freopen("ce.out","w",stdout);
    #endif
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
    if(subtask_0::check()) printf("0\n");
    else if(subtask_1::check()) subtask_1::solve();
    else if(subtask_2::check()) subtask_2::solve();
    else if(n==1) solve_n_1();
    else if(m==1) solve_m_1();
    else if(m==2) others::solve_m_2();
    else others::solve();
    return 0;
}

原文地址:https://www.cnblogs.com/fengxunling/p/11134254.html

时间: 2024-10-06 06:21:51

noi.ac #529 神树的矩阵的相关文章

noi.ac #525 神树的权值

mcfx神仙的题qwq 题目链接:戳我 首先,我们知道30%的分还是挺好做的 直接枚举根,然后dfs一遍以\(O(n)\)的时间复杂度求出来有多少神仙点 代码如下: #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #define MAXN 100010 using namespace std; int n,t; in

noi.ac #528 神树和排列

题目链接:戳我 #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #include<vector> using namespace std; #define MAXN 8010 #define mod 1000000007 #define ll long long int n,m,a[MAXN],flag[

poj 2778 AC自己主动机 + 矩阵高速幂

// poj 2778 AC自己主动机 + 矩阵高速幂 // // 题目链接: // // http://poj.org/problem?id=2778 // // 解题思路: // // 建立AC自己主动机,确定状态之间的关系,构造出,走一步 // 能到达的状态矩阵,然后进行n次乘法,就能够得到状态间 // 走n步的方法数. // 精髓: // 1):这个ac自己主动机有一些特别,根节点是为空串,然而 // 每走一步的时候,假设没法走了,这时候,不一定是回到根 // 节点,由于有可能单个的字符

SDOI2015 寻宝游戏 | noi.ac#460 tree

题目链接:戳我 可以知道,我们相当于是把有宝藏在的地方围了一个圈,求这个圈最小是多大. 显然按照dfs序来遍历是最小的. 那么我们就先来一遍dfs序列,并且预处理出来每个点到根的距离(这样我们就可用\(dis[u]+dis[v]-2*dis[lca(u,v)]\)来表示u,v之间的距离) 怎么动态维护这个东西呢?平衡树?不存在的,开一个set就行了.每次维护一下添加或者删除产生的影响就行了. 相似的题目是noi.ac#460 tree-- 给你一棵n个点的树,每个点都有一个颜色ci. 有m次操作

noi.ac #241 distance

话说这noi.ac是为了给蒟蒻增强信心还是干啥,这比赛后面几题搞的有点水啊.. 虽然第一题比较毒.. 这T3...水的一批... 直接先预处理一下每个点为根的到其他点的距离不就行了吗? 算了不说了... 直接给代码... #include <bits/stdc++.h> #define ll long long using namespace std; const ll N = 10010; ll head[N], Next[N<<1], ver[N<<1], edge

UVA 11019(Matrix Matcher-vector从迭代器中取值,AC自动机匹配字符矩阵)

Problem H Matrix Matcher Input: Standard Input Output: Standard Output Given an N * M matrix, your task is to find the number of occurences of an X * Y pattern. Input The first line contains a single integer t(t ≤ 15), the number of test cases. For e

Hdu 2243 考研路茫茫——单词情结 (AC自己主动机+矩阵)

哎哟喂.中文题. . .不说题意了. 首先做过POJ 2778能够知道AC自己主动机是能够求出长度为L的串中不含病毒串的数量的. POJ 2778的大概思路就是先用全部给的病毒串建一个AC自己主动机.然后将AC自己主动机上全部非单词节点连一个边. 离散数学中有说道.假设矩阵A 中的 [i][j] 表示 i节点通过一条边能够走到j节点的方法数. 那么A*A这个矩阵的[i][j]就表示 i 节点到j 节点通过两条边能够走到j节点的方法数. 既然知道这种方法.我们就明白要求什么. ans= 26+26

【BZOJ2553】[BeiJing2011]禁忌 AC自动机+期望DP+矩阵乘法

[BZOJ2553][BeiJing2011]禁忌 Description Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平.而后,Koishi恢复了读心的能力…… 如今,在John已经成为传说的时代,再次造访那座岛屿的人们却发现Koishi遇到了新麻烦. 这次她遇到了Flandre Scarlet——她拥有可以使用禁忌魔法而不会受到伤害的能力. 为了说明什么是禁忌魔法及其伤害,引入以下概念: 1.字母集A上的每个非空字符

poj2778 DNA Sequence【AC自动机】【矩阵快速幂】

DNA Sequence Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19991   Accepted: 7603 Description It's well known that DNA Sequence is a sequence only contains A, C, T and G, and it's very useful to analyze a segment of DNA Sequence,For ex