【51Nod】1388 六边形平面(枚举情况,判断奇数环)

现在有一个N*N的六边形网格平面(这种平面类似蜂窝形状)。下图是N=1,2,3,4条件下的具体形状,根据它们可以依次类推N=5,6,....。
     


现在你需要对N*N网格中一些格子进行上色,在给定的输入中这些格子被标记上字符‘X’,而不用上色的网格被标记为‘-’。上色时需要注意,如果两个被上色的格子有公共边,那么这两个格子需要被涂成不同的颜色。问最少需要多少种颜色来完成任务?

 收起

输入

多组测试数据,第一行一个整数T,表示测试数据数量,1<=T<=5
每组测试数据有相同的结构构成:
每组数据第一行一个整数N,表示网格大小,其中1<=N<=50.
之后有一个N*N的字符矩阵A,其中A(i,j)为‘X’表示网格中坐标为(i,j)的格子需要被上色,否则不用。

输出

每组数据一行输出,即最少需要的颜色数量.

 

思路:这个题目一开始的我是用的暴力搜索做的,出现了TLE,MLE,WA,AC等等一系列错误

后来看到题解上说的是枚举的他的情况,想了想如果是题中给出的六边形的话确实是只要是3种颜色就足够了,

写的也是这样子的一开始枚举一种的情况,也就是存在,存在‘X’这样的点,

两种颜色的情况,也就是有相邻的边了,这里的相邻弄得比较多,并不是下面和右面相邻而是右下方的三个相邻,还有就是如果这个两种情况的如果其中有奇数环,那么一定是有三种颜色的,这个到最后的我们可以做一个判断

三种情况的就是和两个点都直接相连,这个直接做判断就好

详情见代码

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=50+10;
int dx[]= {-1,0,-1,1,0,1};
int dy[]= {0,-1,1,-1,1,0};
int vis[maxn][maxn];
char mp[maxn][maxn];
int n,ans,flag=0;
void DFS(int x,int y,int step)
{
    vis[x][y]=step;
    for(int i=0; i<6; i++)
    {
        int nx=x+dx[i];
        int ny=y+dy[i];
        if(nx<1||nx>n||ny<1||ny>n)
            continue;
        if(mp[nx][ny]!='X')continue;
        if(vis[nx][ny]==0)
            DFS(nx,ny,step+1);
        else if((abs(vis[x][y]-vis[nx][ny]))%2==0)
            flag=1;
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        //cout<<"n="<<n<<endl;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                cin>>mp[i][j];
        ans=0;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                if(mp[i][j]=='X')
                    ans=1;

        for(int i=1; i<=n; i++)
            for(int j=1; j<=n-1; j++)
                if(mp[i][j]=='X'&&mp[i][j+1]=='X')
                    ans=2;
        for(int i=1; i<=n-1; i++)
            for(int j=1; j<=n; j++)
                if(mp[i][j]=='X'&&mp[i+1][j]=='X')
                    ans=2;
        for(int i=1; i<=n-1; i++)
            for(int j=1; j<=n; j++)
                if(mp[i][j]=='X'&&mp[i+1][j-1]=='X')
                    ans=2;

        for(int i=1; i<=n-1; i++)
            for(int j=1; j<=n-1; j++)
                if(mp[i][j]=='X'&&mp[i+1][j]=='X'&&mp[i][j+1]=='X')
                    ans=3;
        for(int i=1; i<=n-1; i++)
            for(int j=1; j<=n; j++)
                if(mp[i][j]=='X'&&mp[i+1][j-1]=='X'&&mp[i+1][j]=='X')
                    ans=3;
        if(ans==2)
        {
            flag=0;
            memset(vis,0,sizeof(vis));
            for(int i=1; i<=n; i++)
                for(int j=1; j<=n; j++)
                    if(mp[i][j]=='X'&&vis[i][j]==0)
                        DFS(i,j,1);
            ans+=flag;
        }
        printf("%d\n",ans);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值