洛谷 - P2324 - 骑士精神 - A*搜索
为什么估价是16,因为最后一步复原空格可以恢复两个位置,当然设成17、18都可以。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct State {
char g[5][6]; //矩阵的状态,0是白马,1是黑马,规定空格是*
int hstep; //step+估价函数,至少需要的步数
State() {}
int h(); //估价函数h,为未归位的骑士数
void move_to(int id,int step); //尝试移动状态加入优先队列
bool operator==(const State& s)const {
//无序map
for(int i=0; i<5; i++)
for(int j=0; j<5; j++)
if(g[i][j]!=s.g[i][j])
return false;
return true;
}
bool operator<(const State& s)const {
//最大堆
return hstep>s.hstep;
}
} s_state,t_state;
struct State_Hash {
size_t operator()(const State&t)const {
int id=0;
for(int i=0; i<5; i++)
for(int j=0; j<5; j++)
id=(id<<1)+(t.g[i][j]-'0');
return id;
}
};
int State::h() {
//估价函数,因为每次移动的是空格
int res=0;
for(int i=0; i<5; i++)
for(int j=0; j<5; j++)
if(g[i][j]!=t_state.g[i][j])
res++;
return res;
}
//vis从起点开始找到的状态
unordered_map<State,int,State_Hash> vis;
priority_queue<State> pq;
int dx[]= {2,1,-1,-2,-2,-1,1,2};
int dy[]= {1,2,2,1,-1,-2,-2,-1};
void State::move_to(int id,int step) {
//空格向id方向移动
int ox=-1;
int oy=-1;
for(int i=0; i<5; i++) {
for(int j=0; j<5; j++) {
if(g[i][j]=='*') {
ox=i,oy=j;
break;
}
}
}
int nx=ox+dx[id];
int ny=oy+dy[id];
//越界
if(nx<0||ny<0||nx>4||ny>4)
return;
State res=*this;
swap(res.g[ox][oy],res.g[nx][ny]);
res.hstep=step+1+res.h();
if(hstep>16)
return;
if(vis.count(res)) {
return;
} else {
vis[res]=step+1;
pq.push(res);
}
}
//单向A*搜索
bool A_star() {
vis.clear();
while(!pq.empty())
pq.pop();
vis[s_state]=0;
pq.push(s_state);
while(!pq.empty()) {
State curstate=pq.top();
pq.pop();
int curstep=vis[curstate];
for(int i=0; i<8; i++)
curstate.move_to(i,curstep);
if(vis.count(t_state))
return true;
}
return false;
}
int main() {
#ifdef Yinku
freopen("Yinku.in","r",stdin);
#endif // Yinku
strcpy(t_state.g[0],"11111");
strcpy(t_state.g[1],"01111");
strcpy(t_state.g[2],"00*11");
strcpy(t_state.g[3],"00001");
strcpy(t_state.g[4],"00000");;
int T;
scanf("%d",&T);
while(T--) {
for(int i=0; i<5; i++)
scanf("%s",s_state.g[i]);
if(A_star()) {
int ans=vis[t_state];
printf("%d\n",ans>15?-1:ans);
} else {
puts("-1");
}
}
return 0;
}