这道题的题意是:从棋子上的任意一点(边缘、坏的棋子除外),都能按照某一指令走到边缘,求这个最短的指令。
一开始看到这个题的时候一点思路也没有,后来看了一下别人的解题报告,才明白用的是IDA*算法,IDA*算法就是A*算法+迭代。
解题思路为:
1.用BFS求出棋子上所有点到边缘的距离
2.用A*算法进行预先判断,A*算法是预先判断的算法,不同于dfs和bfs这种盲目搜索算法,他可以大大的减少时间的复杂度,如果当前节点的深度+当前状态下棋子上任意一节点到边缘的最大值>确定的最大深度,则return false。
3.运用迭代一次加深进行搜索,最大深度从1开始搜索,一直到找到为止。
代码参考的论坛上某一大神的代码:
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define inf 1<<30;
typedef pair<int,int>PP;
struct Node{
int x,y;
}node[44];
char str[11][11];
int map[11][11],Index[1111],dist[11][11];
int n,m,maxdeep;
int dir[4][2]={{0,1},{-1,0},{1,0},{0,-1}};
bool In_Edge(int x,int y){
if(x==1||x==n||y==1||y==n)
return true;
return false;
}
//bfs用来求到边缘的最短长度
int bfs(int x,int y){
queue<PP>que;
que.push(make_pair(x,y));
int dd[11][11];
memset(dd,-1,sizeof(dd));
dd[x][y]=0;
while(!que.empty()){
x=que.front().first,y=que.front().second;
que.pop();
if(In_Edge(x,y))
return dd[x][y];
for(int i=0;i<4;i++){
int xx=x+dir[i][0],yy=y+dir[i][1];
if(map[xx][yy]&&dd[xx][yy]==-1){
dd[xx][yy]=dd[x][y]+1;
que.push(make_pair(xx,yy));
}
}
}
return -1;
}
int Get_H(Node node[]){
int max_dist=0;
for(int i=0;i<m;i++){
max_dist=max(max_dist,dist[node[i].x][node[i].y]);
}
return max_dist;
}
bool IDA_star(int deep,Node node[]){
//A*剪枝
if(Get_H(node)+deep>maxdeep)
return false;
if(deep==maxdeep)
return true;
Node tmp_node[44];
for(int i=0;i<4;i++){
Index[deep]=i;
for(int j=0;j<m;j++){
int xx=node[j].x+dir[i][0],yy=node[j].y+dir[i][1];
//如果这个方向不能继续往下走
if(In_Edge(node[j].x,node[j].y)||map[xx][yy]==0){
tmp_node[j]=node[j];
}
//这个方向能继续走
else
tmp_node[j].x=xx,tmp_node[j].y=yy;
}
if(IDA_star(deep+1,tmp_node))
return true;
}
return false;
}
int main(){
int t=0;
while(scanf("%d",&n)!=EOF){
if(t++){
puts("");
}
for(int i=1;i<=n;i++){
scanf("%s",str[i]+1);
for(int j=1;j<=n;j++)
map[i][j]=1-(str[i][j]-'0');
}
m=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(map[i][j]){
if(In_Edge(i,j))
dist[i][j]=0;
else{
dist[i][j]=bfs(i,j);
node[m].x=i,node[m++].y=j;
}
}
else{
dist[i][j]=inf;
}
}
}
if(m==0)
continue;
for(maxdeep=1;;maxdeep++){
if(IDA_star(0,node))
break;
}
for(int i=0;i<maxdeep;i++){
if(Index[i]==0)
puts("east");
else if(Index[i]==1)
puts("north");
else if(Index[i]==2)
puts("south");
else if(Index[i]==3)
puts("west");
}
}
return 0;
}