题目大意:
一只小船在水中行走,想要到达目的地,然后有八个方向,用0 …… 7表示,分别是北,东北,东,东南……,而它在任何一点都有一个方向,而当它的下一步走的方向跟它此刻自己的顺风方向相同的时候(即下一步的方向跟它的数字相同),走这一步不需要耗费能量,否则耗费的能量为1个单位能量。然后要求这只小船到达目的地所需的最小能量。
解题思路:
一下来就感觉其实实现的方法比较容易,应该用优先队列的,只是那个状态标志要稍微变一下,走过的点不能简简单单地用visited[],因为由一个点扩张出去,有可能下个点也要走上个点扩张出去的点。因为当前点走到下一个点(即上一个点的扩张出去的点)消耗的能量比上一次的要小,所以要用另一个vst[]来标志这个点已被走过的能量值。只要下一次到达该点的能量值能够小于这个点,那么就可以入队。(注意每个点是可以走多次的哦,想清楚状态很重要)
代码:
#include
#include
const int inf=1000000;
const int MAX=1005;
using namespace std;
typedef struct node
{
int x,y;
int step;
friend bool operator<(const struct node &n1,const struct node &n2)
{
return n1.step>n2.step;
}
}N;
char map[MAX][MAX];
bool visited[MAX][MAX];
int dir[8][2]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
int n,m;
int vst[MAX][MAX];
void init()
{
memset(visited,false,sizeof(visited));
for(int i=0;iQ;
pre.x=sx;
pre.y=sy;
pre.step=0;
vst[pre.x][pre.y]=0;
Q.push(pre);
if(sx==ex && sy==ey)
return 0;
while(!Q.empty())
{
pre=Q.top();
Q.pop();
if(pre.x==ex && pre.y==ey)//终点
return pre.step;
for(int i=0;i<8;i++)
{
cur=pre;
cur.x+=dir[i][0];
cur.y+=dir[i][1];
if(visited[cur.x][cur.y]==false && cur.x>=1 && cur.x<=n && cur.y>=1 && cur.y<=m)
{
if(map[pre.x][pre.y]!=i+'0')
cur.step++;
//visited[cur.x][cur.y]=true;
if(vst[cur.x][cur.y]>cur.step)
{
vst[cur.x][cur.y]=cur.step;
Q.push(cur);
}
}
}
}
return -1;
}
int main(void)
{
while(scanf("%d%d",&n,&m)==2)
{
init();
int i,j;
for(i=1;i<=n;i++)
{
scanf("%s",map[i]+1);
}
int num,sx,sy,ex,ey;
scanf("%d",&num);
for(i=1;i<=num;i++)
{
scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
int ans=BFS(sx,sy,ex,ey);
printf("%d\n",ans);
}
}
return 0;
}