kickstart:Wiggle Walk

kickstart:Wiggle Walk

这道题本身比较麻烦,有四个方向,我们需要找到对应方向的下一个点。

暴力解法:

对于任意一步,当前点p和当前方向d,
记录p的状态为被访问
查询p+d是否被访问过,是则继续查询p+2d,直到找到p+nd没有被访问过,p+nd就是解
这样算法,如果测试例子是EWEWEWEWEWEWEWEWEW这种形式,复杂度是O(N2),hidden的例子这么大肯定过不去

优化解法

我们要优化算法,只能从每一步找对应的边界开始。我的做法和官方分析有出入,我们注意到,每次走完一步停下来的位置,就是之前访问过的某个点的附近一点。如果我们把每次访问的点附近的点都存起来,并剔除掉已经被访问过的点,这些点就是任意方向运动后的可能的位置的集合。那么上下左右四个方向,每个方向的每一行(列)维护一个这个点的集合,每次到一个新的点就把附近的没访问过的点放进去,每次只需在某一行的这些点中找对应的点即可。若使用set,插入删除寻找点的复杂度为O(log(N))。事实上我们只需要维护数值方向和水平方向即可。

#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <string>
#include <set>
using namespace std;
inline long long trans(int r, int c) {
	return r * 51000 + c;
}
void findDir(map<int, set<int>>& ver, map<int, set<int>>& hor, map<long long, short>& m, int r, int c, char d, int& ansR, int& ansC) {
	if (d == 'E') {
		for (auto i = hor[r].begin(); i != hor[r].end(); i++) {
			if (*i > ansC) {
				ansC = *i;
				break;
			}
		}
		ansR = r;
	}
	if (d == 'N') {
		int before = 0;
		for (auto i = ver[c].begin(); i != ver[c].end(); i++) {

			if (before < ansR && (*(i) > ansR)) {
				ansR = before;
				break;
			}
			before = *i;
		}
		ansC = c;
	}
	if (d == 'S') {
		for (auto i = ver[c].begin(); i != ver[c].end(); i++) {
			if (*i > ansR) {
				ansR = *i;
				break;
			}
		}
		ansC = c;
	}
	if (d == 'W') {
		int before = 0;
		for (auto i = hor[r].begin(); i != hor[r].end(); i++) {
			if (before < ansC && (*(i) > ansC)) {
				ansC = before;
				break;
			}
			before = *i;
		}
		ansR = r;
	}
	if (m[trans(ansR - 1, ansC)] == 0) {
		ver[ansC].insert(ansR - 1);
	}
	else {
		ver[ansC].erase(ansR - 1);

	}
	if (m[trans(ansR + 1, ansC)] == 0) {
		ver[ansC].insert(ansR + 1);
	}
	else {
		ver[ansC].erase(ansR + 1);

	}
	if (m[trans(ansR, ansC - 1)] == 0) {
		hor[ansR].insert(ansC - 1);
	}
	else {
		hor[ansR].erase(ansC - 1);

	}
	if (m[trans(ansR, ansC + 1)] == 0) {
		hor[ansR].insert(ansC + 1);
	}
	else {
		hor[ansR].erase(ansC + 1);

	}
	hor[ansR].erase(ansC);
	ver[ansC].erase(ansR);
//	cout << ansR << " " << ansC << endl;







}
int main()
{
	int numTest, row, column;
	cin >> numTest;
	for (int l = 0; l < numTest; l++) {
		map<int, set<int>> neighborVer;
		map<int, set<int>> neighborHor;
		map<long long, short> m;
		string opS;
		int numOp;
		int r, c;
		int sr, sc;
		cin >> numOp >> r >> c >> sr >> sc;
		cin >> opS;
		m[trans(sr, sc)] = 1;
		neighborHor[sr].insert(sc - 1);
		neighborHor[sr].insert(sc + 1);
		neighborVer[sc].insert(sr - 1);
		neighborVer[sc].insert(sr + 1);

		for (int i = 0; i < numOp; i++) {
			char d = opS[i];
			int ansR = sr, ansC = sc;
			findDir(neighborVer, neighborHor, m, sr, sc, d, ansR, ansC);
			sr = ansR;
			sc = ansC;
			m[trans(sr, sc)] = 1;
		}
		cout << "Case #" << l + 1 << ": " << sr << " " << sc << endl;

	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值