[luogu P2324] [SCOI2005]骑士精神
题目描述

输入输出格式
输入格式:
第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。
输出格式:
对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。
输入输出样例
输入样例#1:
2
10110
01*11
10111
01001
00000
01011
110*1
01110
01010
00100
输出样例#1:
7
-1
说明

看了一下ida*,发现真的比a*简单多了。。ida*无非就是设定一个预期步数,然后运用a*的思想,即——
如果当期实际步数+估计剩余步数>预期步数,则return。显然,估计剩余步数一定不超过实际剩余步数,否则会漏掉最优解。
对于这题来说,估计剩余步数可以采取错位数-1。
错位数即每一个位置上与目标不一致的数量,减一是因为可能在最后用1步能减掉2个错位数,毕竟估价函数越小,可能效率越低,但是至少错误率下降了,对与这题,错误率就为0了。
那什么题目适合ida*呢?当预期步数不大,但是每一层状态数很多时,就适合ida*,毕竟这时bfs已经不适用了。
code:


1 %:pragma GCC optimize(4) 2 #include<bits/stdc++.h> 3 #define swap(x,y) ((x)^=(y)^=(x)^=(y)) 4 using namespace std; 5 const int aim[5][5]={{2,2,2,2,2},{1,2,2,2,2},{1,1,0,2,2},{1,1,1,1,2},{1,1,1,1,1}}; 6 const int fl[8][2]={{1,2},{2,1},{-1,2},{-2,1},{1,-2},{2,-1},{-1,-2},{-2,-1}}; 7 int n,s,rea,a[10][10],ori[10][10],dis[10][10]; 8 inline int get() { 9 int ret=0; 10 for (int i=1; i<=n; i++) 11 for (int j=1; j<=n; j++) 12 ret+=(a[i][j]!=aim[i-1][j-1]); 13 return ret; 14 } 15 inline void idastar(int d,int x,int y) { 16 if (rea<=15) return; int c=get(); 17 if (c==0) {rea=d; return;} 18 if (d+c-1>s) return; 19 for (int i=0; i<8; i++) { 20 int xx=x+fl[i][0],yy=y+fl[i][1]; 21 if (xx<1||xx>n||yy<1||yy>n) continue; 22 swap(a[x][y],a[xx][yy]); 23 idastar(d+1,xx,yy); 24 if (rea<=15) return; 25 swap(a[x][y],a[xx][yy]); 26 } 27 } 28 int main() { 29 int T,sx,sy; char c[10]; 30 scanf("%d",&T),n=5; 31 for (; T; T--) { 32 rea=16; 33 for (int i=1; i<=n; i++) { 34 scanf("%s",c+1); 35 for (int j=1; j<=n; j++) 36 ori[i][j]=(c[j]=='*')?0:c[j]-'0'+1; 37 } 38 for (int i=1; i<=n; i++) 39 for (int j=1; j<=5; j++) 40 if (ori[i][j]==0) {sx=i,sy=j; break;} 41 for (s=1; s<=15; s++) { 42 memcpy(a,ori,sizeof a); 43 idastar(0,sx,sy); 44 if (rea<=15) break; 45 } 46 if (rea>15) puts("-1"); else printf("%d\n",rea); 47 } 48 return 0; 49 }
本文深入解析IDA*搜索算法原理及其在骑士精神问题中的应用,通过对比A*算法,阐述IDA*算法的简洁性和高效性。特别针对状态空间大但预期步数有限的问题,IDA*算法展现出其独特优势。
418

被折叠的 条评论
为什么被折叠?



