【poj 2049】finding nemo【待 SPFA&Bellman-Ford】

不是很确定是不是要把写的题都记录下来 ,因为觉得记录还是挺花时间的。但是不知道怎样才能有系统的代码和算法能力的进步。这个学期虽然学了数算课,但是动手能力几乎没有,昨天的上机考都考得怀疑人生了……不知道妹子是不是真的不适合学这个(好吧╮(╯-╰)╭ 我知道答案是适合,但是现实有时候就是让人产生这样的感觉……想找个能够好好讨论的小伙伴几乎没有)。挺孤独的感觉。

题目:http://poj.org/problem?id=2049

大意就是有一个二维迷宫,每个格子的边界有可能是墙、空地或门,墙的范围在[1, 199], 门不限,爸爸在(0,0)点,孩子可能在任意一点(!之前以为孩子不会在小于0或者大于199的地方,RE了好多次)。求爸爸去救孩子需要通过的最少的门的数量。

不是很难的题目,大概就是广搜,我加了动态规划。感觉好low……看大牛们是用SPFA做的,改天研究一下……

思路:用一个laby数组记录迷宫的边(每个元素记录左和下的边的状态),迷宫的格子用左下顶点的坐标代表

从孩子在的格子出发广搜。

/*
 * nemo.cpp
 *
 *  Created on: 2014年12月18日
 */
#include 
#include 
#include 
#include 
#include 
#define INF ((unsigned short)(1 << 15))
#define MAXINF (1 << 30)
using namespace std;
struct cell
{
	unsigned short e1,e2;//左  下。0为空地,1为门, 墙为INF
};
cell laby[202][202];
int doorlaby[202][202];
bool vis[202][202];
int ans = MAXINF;
int Maxx, Maxy;
void travel(int door, int x, int y)
{
	if((x == 0 && y == 0))
	{
//		cout << "rescue success!" << endl;
		ans = ans < door ? ans:door;
//		cout << ans << endl;
	}
	else
	{
		if(doorlaby[x][y] != -1)
		{
			if(doorlaby[x][y] > door)//当前路径更优
			{
				doorlaby[x][y] = door;
			}
			else//当前路径不好
			{
				return;
			}
		}
		else
		{
			doorlaby[x][y] = door;
		}
		unsigned short temp = laby[x][y].e1;//左
		if(temp != INF && x-1 >= 0)
		{
			if(vis[x-1][y] == 0)
			{
				vis[x-1][y] = 1;
//				cout << "going left " << x-1 << ' ' << y << ' ' << door+temp << endl;
				travel(temp+door, x-1, y);
				vis[x-1][y] = 0;
			}
		}
		temp = laby[x][y].e2;//下
		if(temp != INF && y-1 >= 0)
		{
			if(vis[x][y-1] == 0)
			{
				vis[x][y-1] = 1;
//				cout << "going down " << x << ' ' << y-1 << ' ' << door+temp << endl;
				travel(temp+door, x, y-1);
				vis[x][y-1] = 0;
			}
		}
		temp = laby[x+1][y].e1;//右
		if(temp != INF && x+1 <= Maxx)
		{
			if(vis[x+1][y] == 0)
			{
				vis[x+1][y] = 1;
//				cout << "current " << x << ' ' << y << ' ' << door << endl;
//				cout << laby[1][2].e1 << endl;
//				cout << temp << endl;
//				cout << "going right " << x+1 << ' ' << y << ' ' << door+temp << endl;
				travel(temp+door, x+1, y);
				vis[x+1][y] = 0;
			}
		}
		temp = laby[x][y+1].e2;//上
		if(temp != INF && y+1 <= Maxy)
		{
			if(vis[x][y+1] == 0)
			{
				vis[x][y+1] = 1;
//				cout << "going up " << x << ' ' << y+1 << ' ' << door+temp << endl;
				travel(temp+door, x, y+1);
				vis[x][y+1] = 0;
			}
		}
	}
}
int main()
{
	int M, N;
	while(cin >> M >> N && (M != -1))
	{
		memset(laby, 0, sizeof(cell)*202*202);//全部设为空地
		for(int i = 0; i < M; i++)
		{
			int x, y, d, t;
			scanf("%d%d%d%d", &x, &y, &d, &t);
			if(d)//y方向
			{
				for(int j = 0; j < t; j++)
				{
					laby[x][y+j].e1 = INF;
				}
				Maxy = Maxy > y+t ? Maxy : y+t;
				Maxx = Maxx > x ? Maxx: x;
			}
			else//x方向
			{
				for(int j = 0; j < t; j++)
				{
					laby[x+j][y].e2 = INF;
				}
				Maxx = Maxx > x+t ? Maxx : x+t;
				Maxy = Maxy > y ? Maxy: y;
			}
		}//墙的信息
		for(int i = 0 ; i < N; i++)
		{
			int x, y, d;
			scanf("%d%d%d", &x, &y, &d);
			if(d)//y方向
			{
				laby[x][y].e1 = 1;
				Maxy = Maxy > y+1 ? Maxy : y+1;
				Maxx = Maxx > x ? Maxx: x;
			}
			else//x方向
			{
				laby[x][y].e2 = 1;
				Maxx = Maxx > x+1 ? Maxx : x+1;
				Maxy = Maxy > y ? Maxx: y;
			}
		}//门
//		cout << "information in" << endl;
		float p1, p2;
		cin >> p1 >> p2;//nemo的坐标
		if((p1 < 1 && p2 < 1) || p1 < 0 || p2 < 0 || p2 > 199 || p1 > 199)
		{
			cout << 0 << endl;
		}
		else
		{
			memset(vis, 0, sizeof(bool)*202*202);
			memset(doorlaby, -1, sizeof(int)*202*202);
			ans = MAXINF;
//			cout << "going to travel" << endl;
			vis[(int)p1][(int)p2] = 1;
//			cout << laby[1][2].e1 << endl;
			travel(0, (int)p1, (int)p2);//vis初始化
			if(ans == MAXINF)
				cout << -1 << endl;
			else cout << ans << endl;
		}
	}
}



你可能感兴趣的:(数据结构与算法)