http://acm.hdu.edu.cn/showproblem.php?pid=3295
这道题当时的主要问题是如何保持一个图的状态,标记,防止死循环,不过后来想想,不会产生死循环,因为搜索的方向是使格子中数字少的方向。没有标记图,顶多是在队列里重复项,就直接暴力了~~
思路:对地图的每个状态广搜,具体在搜索一个地图的时候,设立一个标记数组,标记这个数字,搜过了~~具体搜相邻数字的时候再一次广搜~~
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define INF 0x3f3f3f3f
#define BUG printf("here!\n")
using namespace std;
int xx[4]={0,1,0,-1};
int yy[4]={1,0,-1,0};
struct node
{
int num[10][10];
int d;
int count;
};
int vis[8][8];
int n,m;
node update(node cur,int count)
{
int i,j;
node temp;
memset(temp.num,0,sizeof(temp.num));
temp.count=cur.count-count;
temp.d=cur.d+1;
for(i=0;i<m;i++)
{
int k=n-1;
for(j=n-1;j>=0;j--)
{
if(cur.num[j][i]!=0)
{
temp.num[k--][i]=cur.num[j][i];
}
}
}
int k=0;
for(i=0;i<=m-1;i++)
{
if(temp.num[n-1][i]!=0)
{
int j;
for(j=n-1;j>=0;j--)
{
temp.num[j][k]=temp.num[j][i];
}
k++;
}
}
while(k!=m)
{
int j;
for(j=n-1;j>=0;j--)
{
temp.num[j][k]=0;
}
k++;
}
return temp;
}
node work(node cur,int x,int y)
{
vis[x][y]=1;
int flag=cur.num[x][y];
cur.num[x][y]=0;
queue<int> q;
q.push(x*m+y);
int count=1;
while(!q.empty())
{
int c=q.front();
q.pop();
x=c/m;
y=c%m;
int i;
for(i=0;i<4;i++)
{
int nx=x+xx[i];
int ny=y+yy[i];
if(nx<0||nx>=n||ny<0||ny>=m)
continue;
if(cur.num[nx][ny]==flag&&!vis[nx][ny])
{
count++;
vis[nx][ny]=1;
cur.num[nx][ny]=0;
q.push(nx*m+ny);
}
}
}
cur=update(cur,count);
return cur;
}
int bfs(node s)
{
queue<node> q;
q.push(s);
while(!q.empty())
{
node cur=q.front();
q.pop();
int i,j;
memset(vis,0,sizeof(vis));
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(vis[i][j]||cur.num[i][j]==0)
continue;
else
{
node next=work(cur,i,j);
if(next.count==0)
return next.d;
q.push(next);
}
}
}
}
return -1;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
int i,j;
node temp;
temp.d=0;
temp.count=0;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
scanf("%d",&temp.num[i][j]);
if(temp.num[i][j]!=0)
temp.count++;
}
int res=bfs(temp);
if(res!=-1)
printf("%d\n",res);
else
printf("0\n");
}
return 0;
}