现在有一个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);
}
}