骑士精神
题目描述
输入输出格式
输入格式:
第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。
输出格式:
对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。
输入输出样例
输入样例:
2 10110 01*11 10111 01001 00000 01011 110*1 01110 01010 00100
输出样例:
7 -1
说明
解析:
经典A*算法,详情看代码注释。。。。。
#include<cstdio> int n; int a[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 zx[9]={0,1,1,2,2,-1,-1,-2,-2},zy[9]={0,2,-2,1,-1,2,-2,1,-1}; char st[6]; int map[6][6]; int h(){ //估计函数; int t=0; for(int i=1;i<=5;i++) for(int j=1;j<=5;j++) t+=(a[i][j]!=map[i][j]); return t; } bool jd(int x,int y){ //判断点(x,y)是否在棋盘内; return x<=5&&x>=1&&y<=5&&y>=1; } void swap(int &x,int &y){ //交换x,y int t=x; x=y; y=t; } bool IDA(int step,int ms){ if(step>ms) return 0;//当前已走步数超过枚举步数,退出; int hx=h(),sx,sy; if(!hx) return 1; //已达到目标棋局,返回; if(hx+step>ms+1) return 0; //统计步数总比最小移动步数大1,故ms+1的情况要都搜一遍; for(int i=1;i<=5;i++) for(int j=1;j<=5;j++) if(map[i][j]==2){sx=i,sy=j;break;} for(int i=1;i<=8;i++) if(jd(sx+zx[i],sy+zy[i])){ swap(map[sx][sy],map[sx+zx[i]][sy+zy[i]]); if(IDA(step+1,ms)) return 1; swap(map[sx][sy],map[sx+zx[i]][sy+zy[i]]);//回溯 } return 0; } int main() { scanf("%d",&n); while(n--){ for(int i=1;i<=5;i++){ scanf("%s",st); for(int j=0;j<5;j++){ if(st[j]==‘0‘||st[j]==‘1‘) map[i][j+1]=st[j]-‘0‘; else map[i][j+1]=2; } } for(int b=0;b<=16;b++){ if(b==16){printf("-1\n");break;}//break还是要加的,否则16步可行的话会输出; if(IDA(0,b)){ printf("%d\n",b); break; } } } return 0; }
时间: 2024-10-04 07:06:57