Description
水叮当得到了一块五颜六色的格子形地毯作为生日礼物,更加特别的是,地毯上格子的颜色还能随着踩踏而改变。
为了讨好她的偶像虹猫,水叮当决定在地毯上跳一支轻盈的舞来卖萌~~~
地毯上的格子有N行N列,每个格子用一个0~5之间的数字代表它的颜色。
水叮当可以随意选择一个0~5之间的颜色,然后轻轻地跳动一步,左上角的格子所在的联通块里的所有格子就会变成她选择的那种颜色。这里连通定义为:两个格子有公共边,并且颜色相同。
由于水叮当是施展轻功来跳舞的,为了不消耗过多的真气,她想知道最少要多少步才能把所有格子的颜色变成一样的。
Input
每个测试点包含多组数据。
每组数据的第一行是一个整数N,表示地摊上的格子有N行N列。
接下来一个N*N的矩阵,矩阵中的每个数都在0~5之间,描述了每个格子的颜色。
N=0代表输入的结束。
Output
对于每组数据,输出一个整数,表示最少步数。
Sample Input
2
0 0
0 0
3
0 1 2
1 1 2
2 2 1
0
Sample Output
0
3
对于100%的数据,N<=8,每个测试点不多于20组数据。
题解
IDA*枚举步数进行搜索,用剩余几种颜色做比较函数,为加速搜索,预处理左上角联通快的边界位置,向外扩展。
代码by hzwer
#include<bits/stdc++.h>
typedef long long ll;
const int N=10000000;
const int mod=1000000007;
const double eps=0.00000001;
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int step,n,mp[9][9],flag[9][9];
int xx[4]={1,-1,0,0},yy[4]={0,0,-1,1},used[6];
bool ans;
int get()
{
int ans=0;
memset(used,0,sizeof(used));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(!used[mp[i][j]]&&flag[i][j]!=1)
{
used[mp[i][j]]=1;
ans++;
}
return ans;
}
void dfs(int a,int b,int c)
{
flag[a][b]=1;
for (int i=0;i<4;i++)
{
int x=a+xx[i],y=b+yy[i];
if (x<1||x>n||y<1||y>n||flag[x][y]==1) continue;
flag[x][y]=2;
if (mp[x][y]==c) dfs(x,y,c);
}
}
bool fill(int c)
{
int ans=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (flag[i][j]==2&&mp[i][j]==c)
{
ans++;
dfs(i,j,c);
}
return ans;
}
void search(int s)
{
int v=get();
if (!v) ans=1;
if (s+v>step||ans) return;
int tmp[10][10];
for(int i=0;i<=5;i++)
{
memcpy(tmp,flag,sizeof(flag));
if(fill(i))search(s+1);
memcpy(flag,tmp,sizeof(flag));
}
}
int main()
{
while (1)
{
n=read();if (n==0) break;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
mp[i][j]=read(),flag[i][j]=0;
dfs(1,1,mp[1][1]);
for (ans=step=0;;step++)
{
search(0);
if (ans){printf("%d\n",step);break;}
}
}
return 0;
}