题目大意: 一只小船在水中行走,想要到达目的地,然后有八个方向,用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;
}
posted on 2011-12-04 13:01  cchun  阅读(151)  评论(0编辑  收藏  举报