Luogu P2324 [SCOI2005]骑士精神
题意
(我也会简化题意了qwq)
给一个矩阵,有一个空格在其中,每次操作可以按规则将其他格子与这个空格交换,多少次达到目标状态?
规则:马在棋盘上跳的规则(当然不存在被堵了马脚的情况quq)
爆搜吗,把空格当马跳,肯定会炸掉的。。。
标签是启发式搜索还有一个神秘的A*算法
sto向骑(xie)士(e)精(ti)神(mu)低头。。。我又膜(bu)了(si)题(kao)解(le)
lhy向我推荐的这篇题解还挺好的
importance:
要把当前相差的方格数记录,努力使相差的方格数减少,还要防止它走回去
#include<cstdio>
#include<cstring>
//0白1黑
int map[10][10],ans,k,tot,sx,sy;
char s1[1010];
int goal[6][6]={0,0,0,0,0,0,
0,1,1,1,1,1,
0,0,1,1,1,1,
0,0,0,2,1,1,
0,0,0,0,0,1,
0,0,0,0,0,0};
int dx[8]={1,1,2,2,-2,-2,-1,-1};
int dy[8]={-2,2,-1,1,-1,1,-2,2};
int dfs(int x,int y,int t,int sum,int back)
{
if(t>15)return 0;
//if(sum>0)
//printf("%d %d %d %d %d\n",x,y,t,sum,back);
if(sum==0&&t<=15)
{
if(t<ans)ans=t;
return 0;
}
for(int i=0;i<8;i++)
{
if(i+back!=7)
{
int xx=x+dx[i];
int yy=y+dy[i];
int fff1=0,fff2=0;
if(xx>=1&&yy>=1&&xx<=5&&yy<=5)
{
int num=sum;fff1=0;fff2=0;
if(map[x][y]!=goal[x][y])fff1=1;
if(map[xx][yy]!=goal[xx][yy])fff2=1;
int b=map[xx][yy];map[xx][yy]=map[x][y];map[x][y]=b;
if(map[xx][yy]==goal[xx][yy])
{
if(fff2)
num--;
}
else
{
if(fff2==0)
num++;
}
if(map[x][y]==goal[x][y])
{
if(fff1)
num--;
}
else
{
if(fff1==0)
num++;
}
if(t+1+num<=17)
dfs(xx,yy,t+1,num,i);
b=map[xx][yy];map[xx][yy]=map[x][y];map[x][y]=b;
}
}
}
}
int main()
{
scanf("%d",&k);
while(k--)
{
ans=999999999,tot=0;
for(int i=1;i<=5;i++)
{
scanf("%s",s1+1);
for(int j=1;j<=5;j++)
{
if(s1[j]=='1')
{
map[i][j]=1;
}
if(s1[j]=='0')
{
map[i][j]=0;
}
if(s1[j]=='*')
{
sx=i;sy=j;
map[i][j]=2;
}
if(map[i][j]!=goal[i][j])tot++;
}
}//printf("%d\n",tot);
/*for(int i=1;i<=5;i++)
{
for(int j=1;j<=5;j++)
{
printf("%d",map[i][j]);
}printf("\n");
}*/
dfs(sx,sy,0,tot,-1);
//x坐标,y坐标,步数,相差数,防止返回的玩意儿
if(ans==999999999)
{
printf("-1\n");continue;
}
printf("%d\n",ans);
}
}
因为一直没看到ans==999999999那里少打了一个=
所以一直不明白为什么只输出-1还多浪费了一个中午QAQ