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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章