欢迎大家访问我的老师的OJ———caioj.cn
题面描述
思路
这道题关键在于怎么确定状态。
一开始想的时候满脑子都是想法
结果想了一会,发现貌似每一个格子都在被遍历到。
那开始的状态就没什么要求了。
那我们就从 ( 1 , 1 ) (1,1) (1,1)左上角开始吧。
将 a [ 1 ] [ 1 ] a[1][1] a[1][1]的颜色标记为 1 1 1.
方向就不用细讲了。
const int dx[4]={0,0,-1,1};
const int dy[4]={-1,1,0,0};
遍历时,碰到不同颜色的格子标记为 2 2 2.
碰到相同颜色的格子标记为 1 1 1,且将状态拓展到那个格子上。
本次递归停下来了,随便找到一个被标记为 2 2 2的格子
继续递归。
但是这样,貌似好像还会超时。
先来个迭代加深吧,限制一下深度,使它不要那么放飞自我
再来个估值函数
是这样设计的
经过慎重的思考,我们可以发现
我们至少要将非标记为1的各种颜色的格子给踩一下,才能使所有格子同一颜色
所以
int gj()
{
int cnt=0;
bool w[6];memset(w,false,sizeof(w));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!w[a[i][j]]&&v[i][j]!=1)
{
cnt++;w[a[i][j]]=1;
}
return cnt;
}
AC code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
const int N=10;
const int dx[4]={0,0,-1,1};
const int dy[4]={-1,1,0,0};
int v[N][N],a[N][N],n,dep;
bool pd(int x,int y){return x>0&&x<=n&&y>0&&y<=n;}
void dfs(int x,int y,int z)
{
v[x][y]=1;
for(int i=0;i<4;i++)
{
int nx=x+dx[i],ny=y+dy[i];
if(!pd(nx,ny))continue;
if(v[nx][ny]==1)continue;
v[nx][ny]=2;if(a[nx][ny]==z)dfs(nx,ny,z);
}
}
int gj()
{
int cnt=0;
bool w[6];memset(w,false,sizeof(w));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!w[a[i][j]]&&v[i][j]!=1)
{
cnt++;w[a[i][j]]=1;
}
return cnt;
}
bool dfs0(int now)
{
int cnt=gj();
if(!cnt)return 1;
if(now+cnt>dep)return 0;
int w[N][N];memcpy(w,v,sizeof(v));
for(int i=0;i<6;i++)
{
bool flag=0;
for(int x=1;x<=n;x++)
for(int y=1;y<=n;y++)
if(v[x][y]==2&&a[x][y]==i)
{
flag=1;dfs(x,y,a[x][y]);
}
if(flag&&dfs0(now+1))return 1;
memcpy(v,w,sizeof(w));
}
return 0;
}
int main()
{
while(scanf("%d",&n)&&n)
{
if(!n)break;memset(v,0,sizeof(v));
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&a[i][j]);
dfs(1,1,a[1][1]);
dep=0;
while(!dfs0(0))dep++;
printf("%d\n",dep);
}
return 0;
}