【洛谷】2324:[SCOI2005]骑士精神【IDA*】
题目描述
输入输出格式
输入格式:
第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位。两组数据之间没有空行。
输出格式:
对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。
输入输出样例
说明
喜欢了!不枉我研究那么久搜索QAQ
不过还是卡了一会儿,因为在估价时不能算空格,空格是跟随别人走的。
然后就是迭代加深和A*的套路了...枚举最大深度,估价剪枝,然后直接暴力跳就行叻!
#include<bits/stdc++.h> using namespace std; int maxdep; int zl[9][2] = {{2, 1}, {-2, 1}, {1, 2}, {-1, 2}, {1, -2}, {-1, -2}, {2, -1}, {-2, -1}}; int st[6][6], now[6][6], G[6][6]; char s[6][10]; void init() { for(int i = 1; i <= 5; i ++) for(int j = 1; j <= 5; j ++) { if(i <= 2 && j >= i) st[i][j] = 1; else if(i <= 3 && j < 3) st[i][j] = 0; else if(i == 3 && j == 3) st[i][j] = 2; else if(i >= 4 && j <= i) st[i][j] = 0; else st[i][j] = 1; } } bool check() { for(int i = 1; i <= 5; i ++) for(int j = 1; j <= 5; j ++) { if(now[i][j] != st[i][j]) return 0; } return 1; } int cot(int x, int y) { int num = 0; for(int i = 1; i <= 5; i ++) for(int j = 1; j <= 5; j ++) if(st[i][j] != now[i][j] && st[i][j] != 2) num ++; return num; } bool pd(int x, int y) { if(x >= 1 && x <= 5 && y >= 1 && y <= 5) return 1; return 0; } int fl, flag; void dfs(int dep, int x, int y) { if(fl) return ; if(dep == maxdep) { if(check()) fl = 1; return ; } if(dep + cot(x, y) > maxdep) return ; for(int i = 0; i < 8; i ++) { int xx = x + zl[i][0], yy = y + zl[i][1]; if(pd(xx, yy)) { swap(now[x][y], now[xx][yy]); dfs(dep + 1, xx, yy); if(fl) return ; swap(now[x][y], now[xx][yy]); } } if(fl) return ; } int main() { int T; scanf("%d\n", &T); init(); while(T --) { int x, y; flag = 0; for(int i = 1; i <= 5; i ++) { scanf("%s", s[i] + 1); } for(int i = 1; i <= 5; i ++) { for(int j = 1; j <= 5; j ++) { if(s[i][j] == '1') G[i][j] = 1; else if(s[i][j] == '0') G[i][j] = 0; else G[i][j] = 2, x = i, y = j; } } for(maxdep = 0; maxdep <= 15; maxdep ++) { fl = 0; for(int i = 1; i <= 5; i ++) for(int j = 1; j <= 5; j ++) now[i][j] = G[i][j]; dfs(0, x, y); if(fl) { printf("%d\n", maxdep); flag = 1; break; } } if(!flag) printf("-1\n"); } return 0; }