[考試記錄] 2024.6.9

XiaoLe_MC發表於2024-06-09

T3 WRONG - Wrong directions

題面翻譯

Farmer John剛剛購買了一臺新型可程式設計拖拉機。為了使拖拉機移動,他輸入一串長度為N的繩子

(1 <= N <= 100,000)僅由字元F,L和R組成。每個'F'指示拖拉機向前移動一個單元,

並且字元'L'和'R'分別導致左右轉90度。拖拉機從原點開始(0,0)

朝北。

透過輸入他想要的命令字串對他的拖拉機進行程式設計後,FJ記得他輸入了一個字元

命令字串不正確,但他不記得是哪一個!例如,他可能在打算輸入'F'或'L'時

string包含字元'R'。請計算拖拉機可能在飛機上的不同位置的數量

最後結果(拖拉機在最終位置所面向的方向無關緊要)。

題目描述

Farmer John has just purchased a fancy new programmable tractor. To make the tractor move, he types in a string of length N

(1 <= N <= 100,000) consisting of only the characters F, L, and R. Each 'F' instructs the tractor to move forward one unit,

and the characters 'L' and 'R' result in left and right turns of 90 degrees, respectively. The tractor starts out at the origin (0,0)

facing north.

After programming his tractor by typing in his intended command string, FJ remembers that he typed exactly one character in

the command string incorrectly, but he can't remember which one!For example, he might have typed 'F' or 'L' when his intended

string contained the character 'R'. Please compute the number of different locations in the plane at which the tractor might

end up as a result (the direction the tractor faces in its final location does not matter).

Input format: * Line 1: Farmer John's intended command string. SAMPLE INPUT: FF INPUT DETAILS: Farmer John wants the tractor to advance forward twice, ideally ending at position (0,2). OUTPUT FORMAT: * Line 1: The number of positions at which the tractor might end up,given that FJ mistypes one of the characters in his command string. SAMPLE OUTPUT 3 OUTPUT DETAILS: There are 4 possible mistyped sequences: FL, FR, LF, an RF. These will land the tractor at (0,1), (0,1), (-1,0), and (1,0) respectively, a total of 3 distinct locations.

解析

由於我們只修改其中一個字元,所以問題就會變的簡單許多。為了減少運算量,可以先預處理出從開始點到中間某一個點時的 \(x\)\(y\) 和方向。同樣預處理出從中間某一個點到終點的 \(x\)\(y\) 和方向,在預處理時就把起點作為 \((0,0)\)

對於修改第 \(k\) 個字元,可以把整段路徑看作 \(1~k-1\)\(k\)\(k+1~len\) 三部分,第一部分和第三部分都預處理過了,只用合併就行了。方向的改變對應著座標的變換,手推一下就行了。在合併的同時記錄一下座標,可以用 map,我用的雜湊表,能快一點。

氧氣有毒建議雜湊乘數取131

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int hmod = 999983, hmax = 1e7 + 5, N = 2e5 + 5;
int len;
int way[4][2] = {{0, 1}, {-1, 0}, {0, -1}, {1, 0}};
int my[4][2] = {{1, 1}, {-1, 1}, {-1, -1}, {1, -1}};
string s;
long long ans;
struct dirt{ int dir, x, y; }ld[N], rd[N];
struct Hash_Table{
	int h[hmod+1], nxt[hmax+1], cnt, vx[hmax+1], vy[hmax+1];
	void Hash_in(int x, int y){
		int hnum = (__int128)(x*131 + y) % hmod;
		for(int i=h[hnum]; i; i=nxt[i])
			if(vx[i] == x && vy[i] == y) return;
		vx[++cnt] = x, vy[cnt] = y, nxt[cnt] = h[hnum], h[hnum] = cnt;
	}
	bool Hash_out(int x, int y){
		int hnum = (__int128)(x*131 + y) % hmod;
		for(int i=h[hnum]; i; i=nxt[i])
			if(vx[i] == x && vy[i] == y) return 1;
		return 0;
	}
}h;
inline void merge(int a, char ch, int b){
	int x = ld[a].x, y = ld[a].y, d = ld[a].dir;
	if(ch == 'F') x += way[d][0], y += way[d][1];
	else d = (d + (ch=='L'?1:-1) + 4) % 4;
	if(d == 0) x += rd[b].x, y += rd[b].y;
	else if(d == 1) x -= rd[b].y, y += rd[b].x;
	else if(d == 2) x -= rd[b].x, y -= rd[b].y;
	else x += rd[b].y, y -= rd[b].x;
	if(!h.Hash_out(x, y)) ++ans, h.Hash_in(x, y);
}
int main(){
	freopen("wrongdir.in", "r", stdin);
	freopen("wrongdir.out", "w", stdout);
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin>>s; len = s.size();
	for(int i=1; i<=len; ++i){
		if(s[i-1] == 'F'){
			ld[i].dir = ld[i-1].dir;
			ld[i].x = ld[i-1].x + way[ld[i].dir][0];
			ld[i].y = ld[i-1].y + way[ld[i].dir][1];
		} else{
			ld[i].dir = (ld[i-1].dir + (s[i-1]=='L'?1:-1) + 4) % 4;
			ld[i].x = ld[i-1].x, ld[i].y = ld[i-1].y;
		}
	}
	for(int i=len; i>0; --i){
		if(s[i-1] == 'F'){
			rd[i].dir = rd[i+1].dir;
			rd[i].x = rd[i+1].x;
			rd[i].y = rd[i+1].y + 1;
		} else{
			rd[i].x = rd[i+1].y;
			rd[i].y = rd[i+1].x * -1;
			if(s[i-1] == 'R') rd[i].dir = (rd[i-1].dir + 3) % 4;
			else{
				rd[i].x *= -1, rd[i].y *= -1;
				rd[i].dir = (rd[i-1].dir + 1) % 4;
			}
		}
	}
	for(int i=1; i<=len; ++i){
		if(s[i-1] == 'F') merge(i-1, 'L', i+1), merge(i-1, 'R', i+1);
		else if(s[i-1] == 'R') merge(i-1, 'F', i+1), merge(i-1, 'L', i+1);
		else merge(i-1, 'F', i+1), merge(i-1, 'R', i+1);
	} return cout<<ans, 0;
}

相關文章