HDU 1035 Robot Motion Union Find 并查集题解

本题的类型我一看就想到使用并查集解了,因为要查找是否有环,这是并查集的典型用法。

但是由于本题数据实在是太水了,故此有人使用直接模拟都过了。这让本题降了个档次。

这里使用并查集解。而且可以根据需要简化并查集函数,代码还是很好打的。

#include <stdio.h>
#include <vector>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <limits.h>
#include <stack>
#include <queue>
#include <set>
#include <map>
using namespace std;

const int MAX_N = 11;
const int MAX_V = MAX_N * MAX_N;

struct Subset
{
	int step, p;
};

Subset sub[MAX_V];
char Maze[MAX_N][MAX_N];
int R, C, sx = 0, sy;

int findPar(int x)
{
	if (sub[x].p) return sub[x].p = findPar(sub[x].p);
	return x;
}

inline void unionTwo(int x, int p)
{
	sub[x].p = p;
}

inline bool isLegal(int r, int c)
{
	return 0<=r && 0 <= c && r<R && c<C;
}

bool exitMaze(int &out, int &loop)
{
	int step = 0, si = sx, sj = sy, sni, snj;
	memset(sub, 0, sizeof(Subset)*(R*C+1));
	while (true)
	{
		step++;
		int p = si * C + sj + 1;//注意下标0不使用,作为空标志
		sub[p].step = step;

		//下一个格
		if (Maze[si][sj] == 'S')
		{
			sni = si+1, snj = sj;
		}
		else if (Maze[si][sj] == 'W')
		{
			sni = si, snj = sj-1;
		}
		else if (Maze[si][sj] == 'E')
		{
			sni = si, snj = sj+1;
		}
		else
		{
			sni = si-1, snj = sj;
		}

		if (!isLegal(sni, snj))//out of one side of Maze
		{
			out = step;
			return true;
		}

		int son = sni * C + snj + 1;//注意0不使用

		int pf = findPar(p);
		int sonf = findPar(son);

		if (pf == sonf)
		{
			out = sub[son].step-1;
			loop = step - out;
			return false;
		}

		unionTwo(son, pf);

		si = sni, sj = snj;
	}
}

int main()
{
	while (~scanf("%d %d %d", &R, &C, &sy) && R)
	{
		getchar();
		for (int i = 0; i < R; i++)
		{
			gets(Maze[i]);
		}
		sy--;
		int out = 0, loop = 0;
		if (exitMaze(out, loop))
		{
			printf("%d step(s) to exit\n", out);
		}
		else
		{
			printf("%d step(s) before a loop of %d step(s)\n", out, loop);
		}
	}
	return 0;
}

HDU 1035 Robot Motion Union Find 并查集题解

时间: 2024-10-13 21:02:21

HDU 1035 Robot Motion Union Find 并查集题解的相关文章

[ACM] hdu 1035 Robot Motion (模拟或DFS)

Robot Motion Problem Description A robot has been programmed to follow the instructions in its path. Instructions for the next direction the robot is to move are laid down in a grid. The possible instructions are N north (up the page) S south (down t

杭电 HDU 1035 Robot Motion

Robot Motion Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7488    Accepted Submission(s): 3431 Problem Description A robot has been programmed to follow the instructions in its path. Instruc

HDU 1035 Robot Motion

Robot Motion Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3466    Accepted Submission(s): 1608 Problem Description A robot has been programmed to follow the instructions in its path. Instruct

HDU 1035 [Robot Motion] 模拟 记忆

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1035 题目大意:给出一个地图,每个点都指定下一步的方向.问移动情况(何时走出地图或几步后进入多长的循环) 关键思想:模拟+记忆化.我的做法是访问过的点vis置1,往后每走一步,走过的所有点vis++,因为每个点都可能是循环的节点.后面回到一个vis>1的点,vis-1就是循环长度了.(也可以记录到每个点的步数,最后点的步数差值就是循环长度) 代码如下 //模拟 记忆.可优化 #include <i

HDU 3172 Virtual Friends 带权并查集 -秩

ll T; while(~scanf("%d",&T)){ while(T--) { = = ... 思路: 用秩合并,看了题解才发现 if(fx == fy)要输出当前集合的秩而不是0... #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <vector> #include <map&

hdu 1829 A Bug&#39;s Life 并查集

点击打开链接 http://acm.hdu.edu.cn/showproblem.php?pid=1829 题意:给出n个关系啊a,b,表示a和b是异性,问是否存在矛盾,即存在a和b是同性. 思路,并查集,用f[i]记录i的父亲,next[i]表示同一个集合里的下一个元素,根据next数组可以遍历出一个集合里的所有元素,len[i]表示i和集合的根的关系,0表示同性,1表示异性. 每输入一个a和b,找到他们的根,如果根相等,那么就判断他们和根的关系,如果和根都是同性关系或者都是异性关系,则表示a

HDU 3047 Zjnu Stadium 带权并查集

题目来源:HDU 3047 Zjnu Stadium 题意:给你一些人 然后每次输入a b c 表示b在距离a的右边c处 求有多少个矛盾的情况 思路:用sum[a] 代表a点距离根的距离 每次合并时如果根一样 判断sum数组是否符合情况 根不一样 合并两棵树 这里就是带权并查集的精髓 sum[y] = sum[a]-sum[b]+x 这里y的没有合并前b的根 #include <cstdio> #include <cstring> using namespace std; cons

hdu 1829 A Bug&#39;s Life 并查集系列

1 #include "cstdio" 2 #include "iostream" 3 #include "cstring" 4 #include "vector" 5 #include "queue" 6 using namespace std; 7 8 #define MAXN 2222 9 int fa[MAXN]; 10 int rnk[MAXN]; //秩 表示某点与根的距离 11 int n,

HDU 3367 Pseudoforest(伪森林)(并查集)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3367 题意:在图论中,如果一个森林中有很多连通分量,并且每个连通分量中至多有一个环,那么这个森林就称为伪森林. 现在给出一个森林,求森林包含的最大的伪森林,其大小通过所有边的权值之和来比较. 分析: 1.一开始想的是:在每个连通分量中求一个最大生成树,然后加一条最大的边,再把每个连通分量算出来的值加起来,但WA了.这并不是最优的,因为还存在这种情况:一个连通分量里最初有两个环,但是伪森林要求最多一个