样例输入:
1
1
2 0
2 1 2
3 3 3 3
4 4 4 4 4
5 5 5 5 5 5
样例输出:
3
数据范围:
对于50%的数据,保证十步及以内有解;
对于70%的数据,保证没有太难了的情况;
对于70%的数据,T≤10;
数据有梯度。
题目分析:
这道题很明显是一道搜索题,A*剪枝就可以了。加一个迭代加深也是没有问题的。下附代码的A*剪枝用的是dfs,但实际上bfs时间才是更优的,但是因为bfs相对难写需要记录状态且空间上有可能会爆(不太确定)。
附代码:
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<ctime>
#include<cmath>
#include<cstring>
#include<string>
#include<cctype>
#include<iomanip>
#include<algorithm>
using namespace std;
const int fx[5]={0,-1,-1,1,1};
const int fy[5]={0,0,-1,0,1};
const int bz[7][7]={0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0,1,1,0,0,0,0,
0,2,2,2,0,0,0,
0,3,3,3,3,0,0,
0,4,4,4,4,4,0,
0,5,5,5,5,5,5};
int t,a[7][7],minn,pox,poy;
bool check;
int readint()
{
char ch;int i=0,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') {ch=getchar();f=-1;}
for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0';
return i*f;
}
int pd()//估价函数,有ret个位置不同,则至少需要ret-1步
{
int ret=-1;
for(int i=1;i<=6;i++)
for(int j=1;j<=i;j++)
if(a[i][j]!=bz[i][j]) ret++;
return ret;
}
void dfs(int x,int y,int num)
{
int bs=pd();
if(bs==-1) {check=true;minn=min(minn,num);return;}
if(num+bs>minn) return;
if(x>minn-num) return;
for(int i=1;i<=4;i++)
{
int x1=x+fx[i];
int y1=y+fy[i];
if(x1>=1&&x1<=6&&y1>=1&&y1<=x1)
{
swap(a[x1][y1],a[x][y]);
dfs(x1,y1,num+1);
swap(a[x1][y1],a[x][y]);
}
}
}
int main()
{
//freopen("blocks.in","r",stdin);
//freopen("blocs.out","w",stdout);
t=readint();
while(t--)
{
minn=20;check=false;
for(int i=1;i<=6;i++)
for(int j=1;j<=i;j++)
{
a[i][j]=readint();
if(a[i][j]==0) pox=i,poy=j;
}
dfs(pox,poy,0);
if(check==true) printf("%d\n",minn);
else printf("too difficult\n");
}
return 0;
}