Luogu P2324 [SCOI2005]騎士精神
阿新 • • 發佈:2019-01-22
題意
(我也會簡化題意了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