Problem:
Problem E:
Automotive Navigation
The International Commission for Perfect Cars (ICPC) has constructed a city scale test course for advanced driver assistance systems. Your company, namely the Automotive Control Machines (ACM), is appointed by ICPC to make test runs on the course.
The test course consists of streets, each running straight either east-west or north-south. No streets of the test course have dead ends, that is, at each end of a street, it meets another one. There are no grade separated streets either, and so if a pair of orthogonal streets run through the same geographical location, they always meet at a crossing or a junction, where a car can turn from one to the other. No U-turns are allowed on the test course and a car never moves outside of the streets.
Oops! You have just received an error report telling that the GPS (Global Positioning System) unit of a car running on the test course was broken and the driver got lost. Fortunately, however, the odometer and the electronic compass of the car are still alive.
You are requested to write a program to estimate the current location of the car from available information. You have the car's location just before its GPS unit was broken. Also, you can remotely measure the running distance and the direction of the car once every time unit. The measured direction of the car is one of north, east, south, and west. If you measure the direction of the car while it is making a turn, the measurement result can be the direction either before or after the turn. You can assume that the width of each street is zero.
The car's direction when the GPS unit was broken is not known. You should consider every possible direction consistent with the street on which the car was running at that time.
Input
The input consists of a single test case. The first line contains four integers $n$, $x_0$, $y_0$, $t$, which are the number of streets ($4 \leq n \leq 50$), $x$- and $y$-coordinates of the car at time zero, when the GPS unit was broken, and the current time ($1 \leq t \leq 100$), respectively. $(x_0, y_0)$ is of course on some street. This is followed by $n$ lines, each containing four integers $x_s$, $y_s$, $x_e$, $y_e$ describing a street from $(x_s, y_s)$ to $(x_e, y_e)$ where $(x_s, y_s) \ne (x_e, y_e)$. Since each street runs either east-west or north-south, $x_s = x_e$ or $y_s = y_e$ is also satisfied. You can assume that no two parallel streets overlap or meet. In this coordinate system, the $x$- and $y$-axes point east and north, respectively. Each input coordinate is non-negative and at most 50. Each of the remaining $t$ lines contains an integer $d_i$ ($1 \leq d_i \leq 10$), specifying the measured running distance from time $i − 1$ to $i$, and a letter $c_i$, denoting the measured direction of the car at time $i$ and being either
N
for north,
E
for east,
W
for west, or
S
for south.
Output
Output all the possible current locations of the car that are consistent with the measurements. If they are
...(truncated)

Submitted solutions:

code_snippet: #include<map>
#include<set>
#include<cmath>
#include<queue>
#include<cctype>
#include<cstdio>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<algorithm>
typedef long long LL;
bool go[55][55][4];
bool f[55][55][1010][4];
struct HN {
	int x, y, s, d;
	HN() {}
	HN(int x, int y, int s, int d): x(x), y(y), s(s), d(d) {}
};
int N, SX, SY, T, S;
struct P {
	int x, y;
	P() {}
	P(int x, int y): x(x), y(y) {}
	bool operator < (const P &t) const {
		if(x != t.x) {
			return x < t.x;
		}
		return y < t.y;
	}
};
char ch[256];
int dx[] = {0, -1, 0, 1}, dy[] = {1, 0, -1, 0};
int dir[1010];
bool check(int s, int d) {
	if(dir[s] == -1) {
		return true;
	}
	return dir[s] == d;
}
void process() {
	memset(f, 0, sizeof(f));
	std::queue<HN> q;
	for(int i = 0; i < 4; i ++) {
		if(go[SX][SY][i]) {
			f[SX][SY][0][i] = true;
			q.push(HN(SX, SY, 0, i));
		}
	}
	while(!q.empty()) {
		HN hn = q.front();
		q.pop();
		int x = hn.x, y = hn.y, s = hn.s, d = hn.d;
		if(s >= S) {
			continue;
		}
		int nx = x + dx[d], ny = y + dy[d], ns = s + 1;
		for(int i = -1; i <= 1; i ++) {
			int nd = (d + i + 4) % 4;
			if(go[nx][ny][nd] && (check(ns, d) || check(ns, nd)) && !f[nx][ny][ns][nd]) {
				f[nx][ny][ns][nd] = true;
				q.push(HN(nx, ny, ns, nd));
			}
		}
	}

	std::vector<P> ans;
	for(int i = 0; i <= 50; i ++) {
		for(int j = 0; j <= 50; j ++) {
			bool ok = false;
			for(int k = 0; k < 4; k ++) {
				if(f[i][j][S][k]) {
					ok = true;
				}
			}
			if(ok) {
				ans.push_back(P(i, j));
			}
		}
	}
	std::sort(ans.begin(), ans.end());
	int n = ans.size();
	for(int i = 0; i < n; i ++) {
		printf("%d %d\n", ans[i].x, ans[i].y);
	}
}
int main() {
	//freopen("test.in", "rb", stdin);
	ch['N'] = 0, ch['W'] = 1, ch['S'] = 2, ch['E'] = 3;
	while(scanf("%d%d%d%d", &N, &SX, &SY, &T) == 4) {
		memset(go, 0, sizeof(go));
		int x1, y1, x2, y2;
		for(int i = 0; i < N; i ++) {
			scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
			if(x1 == x2) {
				if(y1 > y2) {
					std::swap(y1, y2);
				}
				for(int i = y1; i <= y2; i ++) {
					if(i != y1) {
						go[x1][i][2] = true;
					}
					if(i != y2) {
						go[x1][i][0] = true;
					}
				}
			} else {
				if(x1 > x2) {
					std::swap(x1, x2);
				}
				for(int i = x1; i <= x2; i ++) {
					if(i != x1) {
						go[i][y1][1] = true;
					}
					if(i != x2) {
						go[i][y1][3] = true;
					}
				}
			}
		}
		memset(dir, -1, sizeof(dir));
		S = 0;
		int d;
		char s[5];
		for(int i = 0; i < T; i ++) {
			scanf("%d%s", &d, s);
			S += d;
			dir[S] = ch[(int)s[0]];
		}
		process();
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 14968
final_rank: 16

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 51

enum DIR{
	North,
	East,
	South,
	West,
};

int diff_x[4] = {0,1,0,-1},diff_y[4] = {1,0,-1,0};
bool can_move[NUM][NUM][4],dp[2][NUM][NUM][4];
int table[128];
DIR dir_array[4] = {North,East,South,West};

int N;

bool rangeCheck(int x,int y){

	if(x >= 0 && x < NUM && y >= 0 && y < NUM)return true;
	else{
		return false;
	}
}

int main(){

	table['N'] = 0;
	table['E'] = 1;
	table['S'] = 2;
	table['W'] = 3;

	int start_x,start_y,T;
	scanf("%d %d %d %d",&N,&start_x,&start_y,&T);

	for(int i = 0; i < NUM; i++){
		for(int k = 0; k < NUM; k++){
			for(int p = 0; p < 4; p++)can_move[i][k][p] = false;
		}
	}

	//移動可能情報の作成
	int x1,y1,x2,y2;
	for(int loop = 0; loop < N; loop++){

		scanf("%d %d %d %d",&x1,&y1,&x2,&y2);

		if(x1 == x2){ //縦の移動

			for(int y = min(y1,y2); y < max(y1,y2); y++){
				can_move[x1][y][North] = true;
				can_move[x1][y+1][South] = true;
			}

		}else{ //横の移動

			for(int x = min(x1,x2); x < max(x1,x2); x++){
				can_move[x][y1][East] = true;
				can_move[x+1][y1][West] = true;
			}
		}
	}

	int CURRENT = 0,NEXT = 1;

	for(int i = 0; i < NUM; i++){
		for(int k = 0; k < NUM; k++){
			for(int p = 0; p < 4; p++){
				dp[CURRENT][i][k][p] = false; //dp[CURRENT/NEXT][x][y][dir] = true/false
			}
		}
	}

	for(int i = 0; i < 4; i++)dp[CURRENT][start_x][start_y][i] = true;

	int dist,next_x,next_y;
	char buf[2];

	DIR dir;

	for(int loop = 0; loop < T; loop++){

		scanf("%d %s",&dist,buf);
		dir = dir_array[table[buf[0]]];

		for(int count = 0; count < dist; count++){ //合計でdist移動する

			//dp[NEXT]の初期化
			for(int i = 0; i < NUM; i++){
				for(int k = 0; k < NUM; k++){
					for(int p = 0; p < 4; p++){
						dp[NEXT][i][k][p] = false;
					}
				}
			}
			//dp[CURRENT]を走査
			for(int i = 0; i < NUM; i++){ //xのループ
				for(int k = 0; k < NUM; k++){ //yのループ
					for(int p = 0; p < 4; p++){ //今向いている方向
						if(!dp[CURRENT][i][k][p])continue;

						for(int a = 0; a < 4; a++){ //進んだ後に向く方向
							if(abs(p-a) == 2)continue; //Uターン禁止

							next_x = i+diff_x[p]; //今向いている向きに進む
							next_y = k+diff_y[p];

							if(rangeCheck(next_x,next_y) == false || can_move[i][k][p] == false
									|| can_move[next_x][next_y][a] == false)continue; //範囲外または行けないならSKIP

							if(count < dist-1){

								dp[NEXT][next_x][next_y][a] = true;

							}else{ //count == dist-1:向きを考慮する!!

								if(dir_array[p] == dir || dir_array[a] == dir){
									dp[NEXT][next_x][next_y][a] = true;
								}
							}
						}
					}
				}
			}
			swap(CURRENT,NEXT);
		}
	}

	for(int i = 0; i < NUM; i++){
		for(int k = 0; k < NUM; k++){
			for(int a = 0; a < 4; a++){
				if(dp[CURRENT][i][k][a]){
					printf("%d %d\n",i,k);
					break;
				}
			}
		}
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3592
final_rank: 2

code_snippet: // AOJ #1349 Automotive Navigation
// 2025.5.13

#include <bits/stdc++.h>
using namespace std;

int g[52][52];
bool dp[1001][52][52][4];
int meas[1001];

const int dx[4] = {0, 1, -1,  0};
const int dy[4] = {1, 0,  0, -1};

int dir_id(char c){
    if(c=='N') return 0;
    if(c=='E') return 1;
    if(c=='W') return 2;
    if(c=='S') return 3;
    return -1;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n, sx, sy, t;
    cin >> n >> sx >> sy >> t;

    for(int i=0;i<n;i++){
        int x1,y1,x2,y2;
        cin >> x1 >> y1 >> x2 >> y2;
        if(x1==x2){
            if(y1>y2) swap(y1,y2);
            for(int y=y1;y<y2;y++){
                g[x1][y]   |= 1<<0;
                g[x1][y+1] |= 1<<3;
            }
        } else {
            if(x1>x2) swap(x1,x2);
            for(int x=x1;x<x2;x++){
                g[x][y1]   |= 1<<1;
                g[x+1][y1] |= 1<<2;
            }
        }
    }

    int sumd = 0;
    for(int i=0;i<=1000;i++) meas[i] = -1;

    for(int i=0;i<t;i++){
        int d; char buf[5];
        cin >> d >> buf;
        sumd += d;
        meas[sumd] = dir_id(buf[0]);
    }

    for(int d=0;d<4;d++)  dp[0][sx][sy][d] = true;

    for(int s=0; s<sumd; s++){
        for(int x=0; x<=50; x++){
            for(int y=0; y<=50; y++){
                for(int l=0; l<4; l++){
                    if(!dp[s][x][y][l]) continue;
                    int mv = meas[s];
                    for(int p=0; p<4; p++){
                        if(!(g[x][y] & (1<<p))) continue;
                        if(l + p == 3) continue;
                        if(mv != -1 && p!=mv && l!=mv) continue;
                        int nx = x + dx[p], ny = y + dy[p];
                        if(nx<0||nx>50||ny<0||ny>50) continue;
                        dp[s+1][nx][ny][p] = true;
                    }
                }
            }
        }
    }

    int final_mv = meas[sumd];
    set<pair<int,int>> ans;
    for(int x=0;x<=50;x++){
        for(int y=0;y<=50;y++){
            bool ok=false;
            for(int k=0;k<4;k++){
                if(!dp[sumd][x][y][k]) continue;
                if(k == final_mv){ ok=true; break; }
                if(k + final_mv != 3 && (g[x][y] & (1<<final_mv))){ ok=true; break; }
            }
            if(ok) ans.emplace(x,y);
        }
    }
    for(auto &p: ans) cout << p.first << " " << p.second << endl;
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 11188
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;

const int mx=60;
const int dmx=1010;
int Convert(int x,int y){return x*mx+y;}
const string str="NESW";
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
bool seen[mx][mx][4][dmx];

int main(){
	int N,sx,sy,T;
	cin>>N>>sx>>sy>>T;
	sx+=2,sy+=2;

	vector<vector<int>>G(mx*mx);
	while(N--){
		int a,b,c,d;
		cin>>a>>b>>c>>d;
		a+=2,b+=2,c+=2,d+=2;
		if(a==c){
			for(int i=min(b,d);i<max(b,d);i++){
				G[Convert(a,i)].push_back(Convert(a,i+1));
				G[Convert(a,i+1)].push_back(Convert(a,i));
			}
		}else{
			for(int i=min(a,c);i<max(a,c);i++){
				G[Convert(i,b)].push_back(Convert(i+1,b));
				G[Convert(i+1,b)].push_back(Convert(i,b));
			}
		}
	}

	vector<int>info(dmx,-1);
	int goald=0,sum=0;
	for(int i=0;i<T;i++){
		int d;char c;cin>>d>>c;
		sum+=d;
		goald=sum;
		info[sum]=str.find(c);
	}

	//x,y,px,py,dir,dist
	using tup=tuple<int,int,int,int>;
	queue<tup> que;
	que.push({sx,sy,-1,0});

	set<pair<int,int>>ans;

	while(!que.empty()){
		auto[x,y,dir,dist]=que.front();que.pop();

		if(dist>goald)break;


		for(int d=0;d<4;d++){
			int nx=x+dx[d],ny=y+dy[d];
			if(count(G[Convert(x,y)].begin(),G[Convert(x,y)].end(),Convert(nx,ny))==0)continue;
			if(seen[nx][ny][d][dist+1])continue;
			if(dir!=-1&&(dir+4-d)%4==2)continue;
			if(info[dist]!=-1&&info[dist]!=dir&&info[dist]!=d)continue;

			seen[nx][ny][d][dist+1]=true;
			if(dist==goald&&(info[dist]==dir||info[dist]==d)){
				ans.insert({x-2,y-2});
				break;
			}
			
			que.push({nx,ny,d,dist+1});
		}
	}

	for(auto[x,y]:ans)cout<<x<<' '<<y<<endl;
}
accuracy: 1
time_ms: 20
memory_kb: 14268
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;

const int mx=60;
const int dmx=1010;
int Convert(int x,int y){return x*mx+y;}
const string str="NESW";
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
bool seen[mx][mx][4][dmx];

int main(){
	int N,sx,sy,T;
	cin>>N>>sx>>sy>>T;
	sx+=2,sy+=2;

	vector<vector<int>>G(mx*mx);
	while(N--){
		int a,b,c,d;
		cin>>a>>b>>c>>d;
		a+=2,b+=2,c+=2,d+=2;
		if(a==c){
			for(int i=min(b,d);i<max(b,d);i++){
				G[Convert(a,i)].push_back(Convert(a,i+1));
				G[Convert(a,i+1)].push_back(Convert(a,i));
			}
		}else{
			for(int i=min(a,c);i<max(a,c);i++){
				G[Convert(i,b)].push_back(Convert(i+1,b));
				G[Convert(i+1,b)].push_back(Convert(i,b));
			}
		}
	}

	vector<int>info(dmx,-1);
	int goald=0,sum=0;
	for(int i=0;i<T;i++){
		int d;char c;cin>>d>>c;
		sum+=d;
		goald=sum;
		info[sum]=str.find(c);
	}

	//x,y,px,py,dir,dist
	using tup=tuple<int,int,int,int>;
	vector<tup> que;
	que.push_back({sx,sy,-1,0});

	set<pair<int,int>>ans;

	//while(!que.empty()){
	for(int t=0;t<(int)que.size();t++){
		auto[x,y,dir,dist]=que[t];

		if(dist>goald)continue;


		for(int d=0;d<4;d++){
			int nx=x+dx[d],ny=y+dy[d];
			if(count(G[Convert(x,y)].begin(),G[Convert(x,y)].end(),Convert(nx,ny))==0)continue;
			if(seen[nx][ny][d][dist+1])continue;
			if(dir!=-1&&(dir+4-d)%4==2)continue;
			if(info[dist]!=-1&&info[dist]!=dir&&info[dist]!=d)continue;

			if(dist==goald&&(info[dist]==dir||info[dist]==d)){
				ans.insert({x-2,y-2});
				break;
			}
			
			que.push_back({nx,ny,d,dist+1});
		}
	}

	for(auto[x,y]:ans)cout<<x<<' '<<y<<endl;
}
accuracy: 0.03571428571428571
time_ms: 20
memory_kb: 36200
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (n); i++)
#define srep(i, s, t) for(int i = (s); i < (t); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
using i64 = long long;
using f64 = long double;
i64 floor_div(const i64 n, const i64 d) { assert(d != 0); return n / d - static_cast<i64>((n ^ d) <  0 && n % d != 0); }
i64  ceil_div(const i64 n, const i64 d) { assert(d != 0); return n / d + static_cast<i64>((n ^ d) >= 0 && n % d != 0); }

int main() {
    cin.tie(0)->sync_with_stdio(0);
    
    int n, x0, y0, t; cin >> n >> x0 >> y0 >> t;
    const int M = 51;
    auto h = [&](int x, int y) { return x * M + y; };
    vector to(M * M, vector(4, int(-1)));
    rep(_, n) {
        int sx, sy, ex, ey; cin >> sx >> sy >> ex >> ey;
        if(sx == ex) {
            const int x = sx;
            if(sy > ey) swap(sy, ey);
            srep(y, sy, ey) {
                const int u = h(x, y), v = h(x, y + 1);
                to[u][0] = v;
                to[v][2] = u;
            }
        } else {
            const int y = sy;
            if(sx > ex) swap(sx, ex);
            srep(x, sx, ex) {
                const int u = h(x, y), v = h(x + 1, y);
                to[u][1] = v;
                to[v][3] = u;
            }
        }
    }

    vector<int> dir = {-1};
    rep(_, t) {
        int d; char c; cin >> d >> c;
        rep(i, d-1) dir.push_back(-1);
        if(c == 'N') dir.push_back(0);
        if(c == 'E') dir.push_back(1);
        if(c == 'S') dir.push_back(2);
        if(c == 'W') dir.push_back(3);
    }
    const int LAST = dir.back();
    dir.pop_back();

    vector dp(M * M, vector(4, int(0)));
    dp[h(x0, y0)] = vector(4, int(1));
    for(int cons : dir) {
        vector nt(M * M, vector(4, int(0)));
        rep(i, M * M) rep(d, 4) if(dp[i][d]) {
            rep(nd, 4) {
                if(abs(d - nd) == 2) continue;
                if(cons != -1 and d != cons and nd != cons) continue;
                const int ni = to[i][nd];
                if(ni == -1) continue;
                nt[ni][nd] = 1;
            }
        }
        dp = move(nt);
    }

    vector<pair<int, int>> ans;
    rep(i, M * M) {
        bool ok = [&] {
            rep(d, 4) {
                if(abs(d - LAST) == 2) continue;
                if(dp[i][d]) {
                    if(d == LAST) return true;
                    if(to[i][LAST] != -1) return true;
                }
            }
            return false;
        }();
        if(ok) ans.push_back({i / M, i % M});
    }
    sort(ans.begin(), ans.end());
    for(auto [x, y] : ans) cout << x << " " << y << "\n";
}
accuracy: 1
time_ms: 50
memory_kb: 3900
final_rank: 5

code_snippet: #include<bits/stdc++.h>

using namespace std;

#define rep(i, n) for(int i = 0; i < (n); i++)
#define per(i, n) for(int i = (n)-1; i >= 0; i--)
#define rep2(i, l, r) for(int i = (l); i < (r); i++)
#define per2(i, l, r) for(int i = (r)-1; i >= (l); i--)
#define each(e, x) for(auto &e : x)
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define eb emplace_back
#define MM << ' ' <<
#define TT template<typename T>
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

TT bool chmin(T &x, T y) { return x > y ? (x = y, true) : false; }

TT bool chmax(T &x, T y) { return x < y ? (x = y, true) : false; }

TT using minheap = priority_queue<T, vector<T>, greater<T>>;
TT using maxheap = priority_queue<T>;

TT void print(vector<T> v, T x = 0) {
    int n = sz(v);
    rep(i, n) cout << v[i] + x << (i == n - 1 ? '\n' : ' ');
    if (n == 0) cout << '\n';
}

TT void printn(vector<T> v, T x = 0) {
    int n = sz(v);
    rep(i, n) cout << v[i] + x << '\n';
}

TT void rearrange(vector<T> &v) {
    sort(all(v));
    v.erase(unique(all(v)), end(v));
}

TT int lb(vector<T> &v, T x) { return lower_bound(all(v), x) - begin(v); }

TT int ub(vector<T> &v, T x) { return upper_bound(all(v), x) - begin(v); }

const int inf = (1 << 30) - 1;
const ll INF = (1LL << 60) - 1;

struct io_setup {
    io_setup() {
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cout << fixed << setprecision(15);
    }
} io_setup;

int main() {
    int n, x0, y0, t;
    cin >> n >> x0 >> y0 >> t;
    x0 *= 2, y0 *= 2;
    int h = 101, w = 101;
    vector<vector<bool>> road(h, vector<bool>(w, false));
    rep(i, n) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        x1 *= 2, y1 *= 2, x2 *= 2, y2 *= 2;
        if (x1 == x2) {
            rep2(y, min(y1, y2), max(y1, y2) + 1) road[y][x1] = true;
        }
        else {
            rep2(x, min(x1, x2), max(x1, x2) + 1) road[y2][x] = true;
        }
    }
    vector<int> d(t);
    vector<char> dirs(t);
    rep(i, t) cin >> d[i] >> dirs[i], d[i] *= 2;
    int sd = accumulate(all(d), 0);
    vector<char> dl(sd + 1, '.');
    int ns = 0;
    rep(i, t) ns += d[i], dl[ns] = dirs[i];
    string dc = "ENWS";
    int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
    vector f(h, vector(w, vector(4, 0)));
    queue<pair<pii, int>> que;
    auto check = [&](int ny, int nx, int dir) ->bool {
        int ney = ny + dy[dir], nex = nx + dx[dir];
        if (ney < 0 || h <= ney || nex < 0 || w <= nex)
            return false;
        return road[ney][nex];
    };
    rep(dir, 4) if (check(y0, x0, dir)) f[y0][x0][dir] = 1, que.emplace(pair(y0, x0), dir);
    rep(nt, sd) {
        queue<pair<pii, int>> nque;
        vector nf(h, vector(w, vector(4, 0)));
        while (sz(que)) {
            auto [yx, ndir] = que.front();
            que.pop();
            auto [ny, nx] = yx;
            if (nt == sd)
                continue;
            int ney = ny + dy[ndir], nex = nx + dx[ndir];
            rep(dd, 4) {
                if (dd == 2)
                    continue;
                int dir = (ndir + dd) % 4;
                if (!check(ney, nex, dir) || (dl[nt + 1] != '.' && dl[nt + 1] != dc[dir] && dl[nt + 1] != dc[ndir]))
                    continue;
                if (!nf[ney][nex][dir])
                    nf[ney][nex][dir] = 1, nque.emplace(pair(ney, nex), dir);
            }
        }
        swap(f, nf);
        swap(que, nque);
    }
    rep(x, w) rep(y, h) {
        rep(dir, 4) {
            if (f[y][x][dir]) {
                cout << x / 2 << ' ' << y / 2 << endl;
                break;
            }
        }
    }
}
accuracy: 1
time_ms: 420
memory_kb: 4604
final_rank: 11

code_snippet: #include <iostream>
using namespace std;

// Input
int N, SX, SY, T;
int AX[1009], AY[1009], BX[1009], BY[1009];
int D[1009]; char C[1009];
int Total_Time, Direction[1009];

// Dynamic Programming
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
bool Road[1009][1009];
bool dp[1009][109][109][4];

bool check(int ax, int ay) {
	if (ax < 0 || ay < 0 || ax > 100 || ay > 100) return false;
	return Road[ax][ay];
}

void Transition(int tm, int cx, int cy, int dir) {
	int dir0 = (dir + 0) % 4;
	int dir1 = (dir + 1) % 4;
	int dir3 = (dir + 3) % 4;
	cx += dx[dir];
	cy += dy[dir];
	
	// Pattern 1: No turn
	if (check(cx * 2 + dx[dir0], cy * 2 + dy[dir0]) == true) {
		if (Direction[tm+1] == -1 || Direction[tm+1] == dir0) {
			dp[tm+1][cx][cy][dir0] = true;
		}
	}
	
	// Pattern 2: Left Turn
	if (check(cx * 2 + dx[dir3], cy * 2 + dy[dir3]) == true) {
		if (Direction[tm+1] == -1 || Direction[tm+1] == dir0 || Direction[tm+1] == dir3) {
			dp[tm+1][cx][cy][dir3] = true;
		}
	}
	
	// Pattern 3: Right Turn
	if (check(cx * 2 + dx[dir1], cy * 2 + dy[dir1]) == true) {
		if (Direction[tm+1] == -1 || Direction[tm+1] == dir0 || Direction[tm+1] == dir1) {
			dp[tm+1][cx][cy][dir1] = true;
		}
	}
}

int main() {
	// Input
	cin >> N >> SX >> SY >> T;
	for (int i = 1; i <= N; i++) {
		cin >> AX[i] >> AY[i] >> BX[i] >> BY[i];
		if (AX[i] > BX[i]) swap(AX[i], BX[i]);
		if (AY[i] > BY[i]) swap(AY[i], BY[i]);
		for (int j = AX[i] * 2; j <= BX[i] * 2; j++) {
			for (int k = AY[i] * 2; k <= BY[i] * 2; k++) Road[j][k] = true;
		}
	}
	for (int i = 0; i <= 1000; i++) Direction[i] = -1;
	for (int i = 0; i < T; i++) {
		cin >> D[i] >> C[i];
		Total_Time += D[i];
		if (C[i] == 'N') Direction[Total_Time] = 0;
		if (C[i] == 'E') Direction[Total_Time] = 1;
		if (C[i] == 'S') Direction[Total_Time] = 2;
		if (C[i] == 'W') Direction[Total_Time] = 3;
	}
	
	// Dynamic Programming
	if (check(SX * 2 + dx[0], SY * 2 + dy[0]) == true) dp[0][SX][SY][0] = true;
	if (check(SX * 2 + dx[1], SY * 2 + dy[1]) == true) dp[0][SX][SY][1] = true;
	if (check(SX * 2 + dx[2], SY * 2 + dy[2]) == true) dp[0][SX][SY][2] = true;
	if (check(SX * 2 + dx[3], SY * 2 + dy[3]) == true) dp[0][SX][SY][3] = true;
	for (int i = 0; i < Total_Time; i++) {
		for (int j = 0; j <= 50; j++) {
			for (int k = 0; k <= 50; k++) {
				for (int l = 0; l < 4; l++) {
					if (dp[i][j][k][l] == false) continue;
					// cout << i << " " << j << " " << k << " " << l << endl;
					Transition(i, j, k, l);
				}
			}
		}
	}
	
	// Output
	for (int i = 0; i <= 50; i++) {
		for (int j = 0; j <= 50; j++) {
			bool flag = false;
			for (int k = 0; k < 4; k++) {
				if (dp[Total_Time][i][j][k] == true) flag = true;
			}
			if (flag == true) cout << i << " " << j << endl;
		}
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 38372
final_rank: 17

code_snippet: #include <bits/stdc++.h>

#ifdef _MSC_VER
#  include <intrin.h>
#else
#  include <x86intrin.h>
#endif

#include <limits>
#include <type_traits>

namespace suisen {
// ! utility
template <typename ...Types>
using constraints_t = std::enable_if_t<std::conjunction_v<Types...>, std::nullptr_t>;
template <bool cond_v, typename Then, typename OrElse>
constexpr decltype(auto) constexpr_if(Then&& then, OrElse&& or_else) {
    if constexpr (cond_v) {
        return std::forward<Then>(then);
    } else {
        return std::forward<OrElse>(or_else);
    }
}

// ! function
template <typename ReturnType, typename Callable, typename ...Args>
using is_same_as_invoke_result = std::is_same<std::invoke_result_t<Callable, Args...>, ReturnType>;
template <typename F, typename T>
using is_uni_op = is_same_as_invoke_result<T, F, T>;
template <typename F, typename T>
using is_bin_op = is_same_as_invoke_result<T, F, T, T>;

template <typename Comparator, typename T>
using is_comparator = std::is_same<std::invoke_result_t<Comparator, T, T>, bool>;

// ! integral
template <typename T, typename = constraints_t<std::is_integral<T>>>
constexpr int bit_num = std::numeric_limits<std::make_unsigned_t<T>>::digits;
template <typename T, unsigned int n>
struct is_nbit { static constexpr bool value = bit_num<T> == n; };
template <typename T, unsigned int n>
static constexpr bool is_nbit_v = is_nbit<T, n>::value;

// ?
template <typename T>
struct safely_multipliable {};
template <>
struct safely_multipliable<int> { using type = long long; };
template <>
struct safely_multipliable<long long> { using type = __int128_t; };
template <>
struct safely_multipliable<unsigned int> { using type = unsigned long long; };
template <>
struct safely_multipliable<unsigned long int> { using type = __uint128_t; };
template <>
struct safely_multipliable<unsigned long long> { using type = __uint128_t; };
template <>
struct safely_multipliable<float> { using type = float; };
template <>
struct safely_multipliable<double> { using type = double; };
template <>
struct safely_multipliable<long double> { using type = long double; };
template <typename T>
using safely_multipliable_t = typename safely_multipliable<T>::type;

template <typename T, typename = void>
struct rec_value_type {
    using type = T;
};
template <typename T>
struct rec_value_type<T, std::void_t<typename T::value_type>> {
    using type = typename rec_value_type<typename T::value_type>::type;
};
template <typename T>
using rec_value_type_t = typename rec_value_type<T>::type;

} // namespace suisen

// ! type aliases
using i128 = __int128_t;
using u128 = __uint128_t;

template <typename T>
using pq_greater = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T, typename U>
using umap = std::unordered_map<T, U>;

// ! macros (capital: internal macro)
#define OVERLOAD2(_1,_2,name,...) name
#define OVERLOAD3(_1,_2,_3,name,...) name
#define OVERLOAD4(_1,_2,_3,_4,name,...) name

#define REP4(i,l,r,s)  for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l);i<(r);i+=(s))
#define REP3(i,l,r)    REP4(i,l,r,1)
#define REP2(i,n)      REP3(i,0,n)
#define REPINF3(i,l,s) for(std::remove_reference_t<std::remove_const_t<decltype(l)>>i=(l);;i+=(s))
#define REPINF2(i,l)   REPINF3(i,l,1)
#define REPINF1(i)     REPINF2(i,0)
#define RREP4(i,l,r,s) for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l)+fld((r)-(l)-1,s)*(s);i>=(l);i-=(s))
#define RREP3(i,l,r)   RREP4(i,l,r,1)
#define RREP2(i,n)     RREP3(i,0,n)

#define rep(...)    OVERLOAD4(__VA_ARGS__, REP4   , REP3   , REP2   )(__VA_ARGS__)
#define rrep(...)   OVERLOAD4(__VA_ARGS__, RREP4  , RREP3  , RREP2  )(__VA_ARGS__)
#define repinf(...) OVERLOAD3(__VA_ARGS__, REPINF3, REPINF2, REPINF1)(__VA_ARGS__)

#define CAT_I(a, b) a##b
#define CAT(a, b) CAT_I(a, b)
#define UNIQVAR(tag) CAT(tag, __LINE__)
#define loop(n) for (std::remove_reference_t<std::remove_const_t<decltype(n)>> UNIQVAR(loop_variable) = n; UNIQVAR(loop_variable) --> 0;)

#define all(iterable) std::begin(iterable), std::end(iterable)
#define input(type, ...) type __VA_ARGS__; read(__VA_ARGS__)

#ifdef LOCAL
#  define debug(...) debug_internal(#__VA_ARGS__, __VA_ARGS__)

template <class T, class... Args>
void debug_internal(const char* s, T&& first, Args&&... args) {
    constexpr const char* prefix = "[\033[32mDEBUG\033[m] ";
    constexpr const char* open_brakets = sizeof...(args) == 0 ? "" : "(";
    constexpr const char* close_brakets = sizeof...(args) == 0 ? "" : ")";
    std::cerr << prefix << open_brakets << s << close_brakets << ": " << open_brakets << std::forward<T>(first);
    ((std::cerr << ", " << std::forward<Args>(args)), ...);
    std::cerr << close_brakets << "\n";
}

#else
#  define debug(...) void(0)
#endif

// ! I/O utilities

// __int128_t
std::ostream& operator<<(std::ostream& dest, __int128_t value) {
    std::ostream::sentry s(dest);
    if (s) {
        __uint128_t tmp = value < 0 ? -value : value;
        char buffer[128];
        char* d = std::end(buffer);
        do {
            --d;
            *d = "0123456789"[tmp % 10];
            tmp /= 10;
        } while (tmp != 0);
        if (value < 0) {
            --d;
            *d = '-';
        }
        int len = std::end(buffer) - d;
        if (dest.rdbuf()->sputn(d, len) != len) {
            dest.setstate(std::ios_base::badbit);
        }
    }
    return dest;
}
// __uint128_t
std::ostream& operator<<(std::ostream& dest, __uint128_t value) {
    std::ostream::sentry s(dest);
    if (s) {
        char buffer[128];
        char* d = std::end(buffer);
        do {
            --d;
            *d = "0123456789"[value % 10];
            value /= 10;
        } while (value != 0);
        int len = std::end(buffer) - d;
        if (dest.rdbuf()->sputn(d, len) != len) {
            dest.setstate(std::ios_base::badbit);
        }
    }
    return dest;
}

// pair
template <typename T, typename U>
std::ostream& operator<<(std::ostream& out, const std::pair<T, U>& a) {
    return out << a.first << ' ' << a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::ostream& operator<<(std::ostream& out, const std::tuple<Args...>& a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return out;
    } else {
        out << std::get<N>(a);
        if constexpr (N + 1 < std::tuple_size_v<std::tuple<Args...>>) {
            out << ' ';
        }
        return operator<<<N + 1>(out, a);
    }
}
// vector
template <typename T>
std::ostream& operator<<(std::ostream& out, const std::vector<T>& a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
// array
template <typename T, size_t N>
std::ostream& operator<<(std::ostream& out, const std::array<T, N>& a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
inline void print() { std::cout << '\n'; }
template <typename Head, typename... Tail>
inline void print(const Head& head, const Tail &...tails) {
    std::cout << head;
    if (sizeof...(tails)) std::cout << ' ';
    print(tails...);
}
template <typename Iterable>
auto print_all(const Iterable& v, std::string sep = " ", std::string end = "\n") -> decltype(std::cout << *v.begin(), void()) {
    for (auto it = v.begin(); it != v.end();) {
        std::cout << *it;
        if (++it != v.end()) std::cout << sep;
    }
    std::cout << end;
}

__int128_t parse_i128(std::string& s) {
    __int128_t ret = 0;
    for (int i = 0; i < int(s.size()); i++) if ('0' <= s[i] and s[i] <= '9') ret = 10 * ret + s[i] - '0';
    if (s[0] == '-') ret = -ret;
    return ret;
}
__uint128_t parse_u128(std::string& s) {
    __uint128_t ret = 0;
    for (int i = 0; i < int(s.size()); i++) if ('0' <= s[i] and s[i] <= '9') ret = 10 * ret + s[i] - '0';
    return ret;
}
// __int128_t
std::istream& operator>>(std::istream& in, __int128_t& v) {
    std::string s;
    in >> s;
    v = parse_i128(s);
    return in;
}
// __uint128_t
std::istream& operator>>(std::istream& in, __uint128_t& v) {
    std::string s;
    in >> s;
    v = parse_u128(s);
    return in;
}
// pair
template <typename T, typename U>
std::istream& operator>>(std::istream& in, std::pair<T, U>& a) {
    return in >> a.first >> a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::istream& operator>>(std::istream& in, std::tuple<Args...>& a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return in;
    } else {
        return operator>><N + 1>(in >> std::get<N>(a), a);
    }
}
// vector
template <typename T>
std::istream& operator>>(std::istream& in, std::vector<T>& a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
// array
template <typename T, size_t N>
std::istream& operator>>(std::istream& in, std::array<T, N>& a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
template <typename ...Args>
void read(Args &...args) {
    (std::cin >> ... >> args);
}

// ! integral utilities

// Returns pow(-1, n)
template <typename T>
constexpr inline int pow_m1(T n) {
    return -(n & 1) | 1;
}
// Returns pow(-1, n)
template <>
constexpr inline int pow_m1<bool>(bool n) {
    return -int(n) | 1;
}

// Returns floor(x / y)
template <typename T>
constexpr inline T fld(const T x, const T y) {
    return (x ^ y) >= 0 ? x / y : (x - (y + pow_m1(y >= 0))) / y;
}
template <typename T>
constexpr inline T cld(const T x, const T y) {
    return (x ^ y) <= 0 ? x / y : (x + (y + pow_m1(y >= 0))) / y;
}

template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u32(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u32(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u64(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clzll(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctzll(x) : suisen::bit_num<T>; }
template <typename T>
constexpr inline int floor_log2(const T x) { return suisen::bit_num<T> -1 - count_lz(x); }
template <typename T>
constexpr inline int ceil_log2(const T x) { return floor_log2(x) + ((x & -x) != x); }
template <typename T>
constexpr inline int kth_bit(const T x, const unsigned int k) { return (x >> k) & 1; }
template <typename T>
constexpr inline int parity(const T x) { return popcount(x) & 1; }

// ! container

template <typename T, typename Comparator, suisen::constraints_t<suisen::is_comparator<Comparator, T>> = nullptr>
auto priqueue_comp(const Comparator comparator) {
    return std::priority_queue<T, std::vector<T>, Comparator>(comparator);
}

template <typename Iterable>
auto isize(const Iterable& iterable) -> decltype(int(iterable.size())) {
    return iterable.size();
}

template <typename T, typename Gen, suisen::constraints_t<suisen::is_same_as_invoke_result<T, Gen, int>> = nullptr>
auto generate_vector(int n, Gen generator) {
    std::vector<T> v(n);
    for (int i = 0; i < n; ++i) v[i] = generator(i);
    return v;
}
template <typename T>
auto generate_range_vector(T l, T r) {
    return generate_vector(r - l, [l](int i) { return l + i; });
}
template <typename T>
auto generate_range_vector(T n) {
    return generate_range_vector(0, n);
}

template <typename T>
void sort_unique_erase(std::vector<T>& a) {
    std::sort(a.begin(), a.end());
    a.erase(std::unique(a.begin(), a.end()), a.end());
}

template <typename InputIterator, typename BiConsumer>
auto foreach_adjacent_values(InputIterator first, InputIterator last, BiConsumer f) -> decltype(f(*first++, *last), void()) {
    if (first != last) for (auto itr = first, itl = itr++; itr != last; itl = itr++) f(*itl, *itr);
}
template <typename Container, typename BiConsumer>
auto foreach_adjacent_values(Container c, BiConsumer f) -> decltype(c.begin(), c.end(), void()) {
    foreach_adjacent_values(c.begin(), c.end(), f);
}

// ! other utilities

// x <- min(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmin(T& x, const T& y) {
    if (y >= x) return false;
    x = y;
    return true;
}
// x <- max(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmax(T& x, const T& y) {
    if (y <= x) return false;
    x = y;
    return true;
}

template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::string bin(T val, int bit_num = -1) {
    std::string res;
    if (bit_num >= 0) {
        for (int bit = bit_num; bit-- > 0;) res += '0' + ((val >> bit) & 1);
    } else {
        for (; val; val >>= 1) res += '0' + (val & 1);
        std::reverse(res.begin(), res.end());
    }
    return res;
}

template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::vector<T> digits_low_to_high(T val, T base = 10) {
    std::vector<T> res;
    for (; val; val /= base) res.push_back(val % base);
    if (res.empty()) res.push_back(T{ 0 });
    return res;
}
template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::vector<T> digits_high_to_low(T val, T base = 10) {
    auto res = digits_low_to_high(val, base);
    std::reverse(res.begin(), res.end());
    return res;
}

template <typename T>
std::string join(const std::vector<T>& v, const std::string& sep, const std::string& end) {
    std::ostringstream ss;
    for (auto it = v.begin(); it != v.end();) {
        ss << *it;
        if (++it != v.end()) ss << sep;
    }
    ss << end;
    return ss.str();
}

namespace suisen {}
using namespace suisen;
using namespace std;

struct io_setup {
    io_setup(int precision = 20) {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(precision);
    }
} io_setup_{};

// ! code from here

constexpr int K = 50;

constexpr int dx[4]{ 1, 0, -1, 0 };
constexpr int dy[4]{ 0, 1, 0, -1 };
constexpr int E = 0, N = 1, W = 2, S = 3;

int main() {
    array<int, 256> ch_to_d{};
    ch_to_d['E'] = E;
    ch_to_d['N'] = N;
    ch_to_d['W'] = W;
    ch_to_d['S'] = S;

    input(int, n, x0, y0, t);

    vector h(K, vector<int8_t>(K + 1, false));
    vector v(K + 1, vector<int8_t>(K, false));

    loop(n) {
        input(int, x1, y1, x2, y2);

        if (x1 == x2) {
            if (y1 > y2) swap(y1, y2);
            rep(y, y1, y2) {
                v[x1][y] = true;
            }
        } else if (y1 == y2) {
            if (x1 > x2) swap(x1, x2);
            rep(x, x1, x2) {
                h[x][y1] = true;
            }
        }
    }

    auto try_succ = [&](int x, int y, int d) -> optional<pair<int, int>> {
        if (d == E) {
            if (x == K or not h[x][y]) return std::nullopt;
            return pair{ x + 1, y };
        } else if (d == W) {
            if (x == 0 or not h[x - 1][y]) return std::nullopt;
            return pair{ x - 1, y };
        } else if (d == N) {
            if (y == K or not v[x][y]) return std::nullopt;
            return pair{ x, y + 1 };
        } else {
            if (y == 0 or not v[x][y - 1]) return std::nullopt;
            return pair{ x, y - 1 };
        }
    };

    vector<tuple<int, int, int>> st;
    st.emplace_back(x0, y0, 0b1111);

    loop(t) {
        input(int, dist);
        input(char, dir_ch);
        const int dir = ch_to_d[dir_ch];

        rep(cur_dist, dist - 1) {
            vector<tuple<int, int, int>> nst;
            for (auto [x, y, pd] : st) {
                rep(d, 4) if (kth_bit(pd, d)) {
                    auto nxy = try_succ(x, y, d);
                    if (not nxy.has_value()) continue;
                    auto [nx, ny] = *nxy;
                    nst.emplace_back(nx, ny, 0b1111 & ~(1 << (d ^ 2)));
                }
            }
            sort_unique_erase(nst);
            nst.swap(st);
        }

        vector<tuple<int, int, int>> nst;
        for (auto [x, y, pd] : st) {
            rep(d, 4) if (kth_bit(pd, d)) {
                auto nxy = try_succ(x, y, d);
                if (not nxy.has_value()) continue;
                auto [nx, ny] = *nxy;
                nst.emplace_back(nx, ny, (d == dir ? 0b1111 : 1 << dir) & ~(1 << (d ^ 2)));
            }
        }
        sort_unique_erase(nst);
        nst.swap(st);
    }

    vector<pair<int, int>> ans;
    for (auto [x, y, pd] : st) {
        rep(d, 4) if (kth_bit(pd, d)) {
            auto nxy = try_succ(x, y, d);
            if (not nxy.has_value()) continue;
            ans.emplace_back(x, y);
        }
    }
    sort_unique_erase(ans);

    print_all(ans, "\n");

    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3600
final_rank: 6

code_snippet: #line 1 "c.cpp"
/*	author:  Kite_kuma
	created: 2022.05.30 15:48:54 */

#line 2 "SPJ-Library/template/kuma.hpp"

#line 2 "SPJ-Library/template/basic_func.hpp"

#include <algorithm>
#include <cassert>
#include <iostream>
#include <vector>

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool flag = true) { std::cout << (flag ? "Yes" : "No") << '\n'; }
void YES(bool flag = true) { std::cout << (flag ? "YES" : "NO") << '\n'; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(const T &x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(const Head &H, const Tail &... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T value) {
	for(auto &a : v) a += value;
	return;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

// ceil(a / b);
template <class T>
T dup(T a, T b) {
	assert(b);
	if(b < 0) {
		a *= -1;
		b *= -1;
	}
	return least_upper_multiple(a, b) / b;
}

long long pow_ll(long long a, long long n) {
	assert(n >= 0LL);
	if(n == 0) return 1LL;
	if(a == 0) return 0LL;
	if(a == 1) return 1LL;
	if(a == -1) return (n & 1LL) ? -1LL : 1LL;
	long long res = 1;
	while(n > 1LL) {
		if(n & 1LL) res *= a;
		a *= a;
		n >>= 1;
	}
	return res * a;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, const long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return (int)std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(const std::vector<T> &a) {
	std::vector<T> vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(const auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}
#line 1 "SPJ-Library/template/header.hpp"
#include <bits/stdc++.h>
#line 2 "SPJ-Library/template/io.hpp"

#line 4 "SPJ-Library/template/io.hpp"

#line 8 "SPJ-Library/template/debug.hpp"

#line 3 "SPJ-Library/template/constants.hpp"

constexpr int inf = 1000'000'000;
constexpr long long INF = 1'000'000'000'000'000'000LL;
constexpr int mod_1000000007 = 1000000007;
constexpr int mod_998244353 = 998244353;
const long double pi = acosl(-1.);
constexpr int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
constexpr int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
#line 10 "SPJ-Library/template/debug.hpp"

namespace viewer {

template <typename T, typename U>
void view(const std::pair<T, U> &p);

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p);

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p);

void view(const long long &e);

void view(const int &e);

template <typename T>
void view(const T &e);

template <typename T>
void view(const std::set<T> &s);

template <typename T>
void view(const std::unordered_set<T> &s);

template <typename T>
void view(const std::multiset<T> &s);

template <typename T>
void view(const std::unordered_multiset<T> &s);

template <typename T>
void view(const std::vector<T> &v);

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v);

template <typename T>
void view(const std::vector<std::vector<T>> &vv);

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v);

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v);

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v);

template <typename map_type>
void view_map_container(const map_type &m);

template <typename T, typename U>
void view(const std::map<T, U> &m);

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m);

template <typename container_type>
void view_container(const container_type &c, bool vertically = false) {
	typename container_type::const_iterator begin = c.begin();
	const typename container_type::const_iterator end = c.end();
	if(vertically) {
		std::cerr << "{\n";
		while(begin != end) {
			std::cerr << '\t';
			view(*(begin++));
			if(begin != end) std::cerr << ',';
			std::cerr << '\n';
		}
		std::cerr << '}';
		return;
	}
	std::cerr << "{ ";
	while(begin != end) {
		view(*(begin++));
		if(begin != end) std::cerr << ',';
		std::cerr << ' ';
	}
	std::cerr << '}';
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << '(';
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ')';
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ')';
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << '(';
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ')';
}

void view(const long long &e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int &e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T &e) {
	std::cerr << e;
}

template <typename T>
void view(const std::set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::unordered_multiset<T> &s) {
	view_container(s);
}

template <typename T>
void view(const std::vector<T> &v) {
	view_container(v);
}

template <typename T, std::size_t ary_size>
void view(const std::array<T, ary_size> &v) {
	view_container(v);
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	view_container(vv, true);
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	view_container(v, true);
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	view_container(v, true);
}

template <typename map_type>
void view_map_container(const map_type &m) {
	std::cerr << "{\n";
	for(typename map_type::const_iterator it = m.begin(); it != m.end(); it++) {
		std::cerr << "\t[";
		view(it->first);
		std::cerr << "] : ";
		view(it->second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	view_map_container(m);
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	view_map_container(m);
}

}  // namespace viewer

// when compiling : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename T>
void debug_out(const T &x) {
	viewer::view(x);
}
template <typename Head, typename... Tail>
void debug_out(const Head &H, const Tail &... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "]\n";                                       \
	} while(0)
#else
#define debug(...) (void(0))
#endif
#line 2 "SPJ-Library/template/scanner.hpp"

#line 6 "SPJ-Library/template/scanner.hpp"

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#line 7 "SPJ-Library/template/io.hpp"

#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}

template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << ' ' << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(typename std::vector<T>::const_iterator it = v.begin(); it != v.end(); it++) {
		if(it != v.begin()) std::cerr << ' ';
		os << *it;
	}
	return os;
}

struct fast_io {
	fast_io() {
		std::ios::sync_with_stdio(false);
		std::cin.tie(nullptr);
		std::cout << std::fixed << std::setprecision(15);
		srand((unsigned)time(NULL));
	}
} fast_io_;
#line 2 "SPJ-Library/template/macros.hpp"

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;
#line 7 "SPJ-Library/template/kuma.hpp"

using namespace std;
#line 5 "c.cpp"

void solve(int n) {
	int x, y, time_end;
	cin >> x >> y >> time_end;
#ifdef LOCAL
	const int len = 53;
#else
	const int len = 53;
#endif
	const int dir_max = 4;
	VVV<int> can_go(len, vvi(len, vi(dir_max, 0)));
	rep(n) {
		int x1, y1;
		cin >> x1 >> y1;
		INT(x2, y2);
		int direction = 0;
		int distance = abs(x1 + y1 - (x2 + y2));
		if(x1 < x2) {
			direction = 0;
		} else if(x1 > x2) {
			direction = 2;
		} else if(y1 < y2) {
			direction = 1;
		} else {
			direction = 3;
		}
		assert(x1 + dx[direction] * distance == x2 && y1 + dy[direction] * distance == y2);
		int rev_dir = (direction + 2) % dir_max;
		while(x1 != x2 || y1 != y2) {
			int nxtx = x1 + dx[direction];
			int nxty = y1 + dy[direction];
			can_go[x1][y1][direction] = 1;
			can_go[nxtx][nxty][rev_dir] = 1;
			x1 = nxtx;
			y1 = nxty;
		}
	}

	vector<pair<int, int>> conditions;
	map<char, int> ch_dir;
	ch_dir['N'] = 1;
	ch_dir['E'] = 0;
	ch_dir['S'] = 3;
	ch_dir['W'] = 2;

	int dist = 0;
	rep(time_end) {
		int t;
		cin >> t;
		dist += t;
		char c;
		cin >> c;
		assert(ch_dir.count(c));
		conditions.emplace_back(dist, ch_dir[c]);
	}

	auto it = conditions.begin();

	vector<vector<vi>> ok(len, vvi(len, vi(dir_max, 0)));
	rep(dir, dir_max) ok[x][y][dir] = 1;

	// debug(can_go);

	rep(dist_now, 1, dist + 1) {
		vvvi tmp(len, vvi(len, vi(dir_max, 0)));

		rep(i, len) rep(j, len) rep(dir, dir_max) {
			if(ok[i][j][dir] && can_go[i][j][dir]) {
				tmp[i + dx[dir]][j + dy[dir]][dir] = 1;
			}
		}

		foa(vv, ok) foa(v, vv) foa(c, v) c = 0;

		rep(i, len) rep(j, len) {
			rep(dir, dir_max) if(tmp[i][j][dir]) {
				rep(nxtdir, dir - 1, dir + 2) {
					if(can_go[i][j][(nxtdir + dir_max) % dir_max]) {
						ok[i][j][(nxtdir + dir_max) % dir_max] = 1;
					}
				}
			}
		}

		if(dist_now == it->first) {
			rep(i, len) rep(j, len) rep(d, dir_max) {
				if(d != it->second) ok[i][j][d] = 0;
			}

			const int dir = it->second;
			rep(i, len) rep(j, len) {
				if(tmp[i][j][dir]) {
					rep(nxtdir, dir - 1, dir + 2) {
						if(can_go[i][j][(nxtdir + dir_max) % dir_max]) {
							ok[i][j][(nxtdir + dir_max) % dir_max] = 1;
						}
					}
				}
			}

			it++;
		}

		rep(i, len) rep(j, len) rep(d, dir_max) {
			if(ok[i][j][d]) {
				debug(dist_now, i, j, d);
			}
		}
	}
	assert(it == conditions.end());
	debug(conditions);

	rep(i, len) rep(j, len) {
		if(*max_element(all(ok[i][j]))) print(i, j);
	}

#ifdef LOCAL
	print("finish!!");
#endif

	return;
}

int main() {
	int n;
	while(cin >> n && n) solve(n);

	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3928
final_rank: 7

code_snippet: #include<bits/stdc++.h>
#define rep(i,a,...) for(int i = (a)*(strlen(#__VA_ARGS__)!=0);i<(int)(strlen(#__VA_ARGS__)?__VA_ARGS__:(a));++i)
#define per(i,a,...) for(int i = (strlen(#__VA_ARGS__)?__VA_ARGS__:(a))-1;i>=(int)(strlen(#__VA_ARGS__)?(a):0);--i)
#define foreach(i, n) for(auto &i:(n))
#define all(x) (x).begin(), (x).end()
#define bit(x) (1ll << (x))
#define lambda(RES_TYPE, ...) (function<RES_TYPE(__VA_ARGS__)>)[&](__VA_ARGS__) -> RES_TYPE
#define method(FUNC_NAME, RES_TYPE, ...) function<RES_TYPE(__VA_ARGS__)> FUNC_NAME = lambda(RES_TYPE, __VA_ARGS__)
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
//const ll MOD = (ll)1e9+7;
const ll MOD = 998244353;
const int INF = (ll)1e9+7;
const ll INFLL = (ll)1e18;
template<class t>
using vvector = vector<vector<t>>;
template<class t>
using vvvector = vector<vector<vector<t>>>;
template<class t>
using priority_queuer = priority_queue<t, vector<t>, greater<t>>;
template<class t, class u> bool chmax(t &a, u b){if(a<b){a=b;return true;}return false;}
template<class t, class u> bool chmin(t &a, u b){if(a>b){a=b;return true;}return false;}
#ifdef DEBUG
#define debug(x) cout<<"LINE "<<__LINE__<<": "<<#x<<" = "<<x<<endl;
#else
#define debug(x) (void)0
#endif

namespace templates{
    ll modpow(ll x, ll b,ll mod=MOD){
        ll res = 1;
        while(b){
            if(b&1)res = res * x % mod;
            x = x * x % mod;
            b>>=1;
        }
        return res;
    }

    ll modinv(ll x){
        return modpow(x, MOD-2);
    }

    bool was_output = false;

    void print();
    template <class t> void print(const vector<t> &);
    template <class t, class u> void print(const pair<t, u> &);
    template <class t> void print(const t&);
    template <class Head, class... Tail> void print(const Head&, const Tail&...);

    template <class t> void println(const vector<vector<t>>&);
    template <class t> void println(const vector<t>&);
    template <class t> void println(const t&);
    template <class Head, class... Tail> void println(const Head&, const Tail&...);
    void println();
    void newline();

    void print(){
        return;
    }

    template <class t>
    void print(const vector<t>&x){
        for(const t&i:x)print(i);
    }
    template <class t, class u>
    void print(const pair<t,u>&p){
        print(p.first);
        print(p.second);
    }
    template <class t>
    void print(const t&x){
        if(was_output)cout<<" ";
        cout<<x;
        was_output = true;
    }
    template <class Head, class... Tail>
    void print(const Head&head,const Tail&...tail){
        print(head);
        print(tail...);
    }

    template<class t>
    void println(const vector<vector<t>>&x){
        for(vector<t> i:x)println(i);
    }
    template<class t>
    void println(const vector<t>&x){
        for(const t&i:x)print(i);
        println();
    }
    template <class t>
    void println(const t&x){
        print(x);
        println();
    }
    void println(){
        if(was_output){
            cout << endl;
            was_output = false;
        }
    }
    template <class Head, class... Tail>
    void println(const Head&head,const Tail&...tail){
        print(head);
        println(tail...);
    }

    void newline(){
        was_output = true;
        println();
    }

    template<class t>
    istream& operator>>(istream&is, vector<t>&x){
        for(auto &i:x)is >> i;
        return is;
    }

    template<class t, class u>
    istream& operator>>(istream&is, pair<t, u>&x){
        is >> x.first >> x.second;
        return is;
    }

    template<class t>
    ostream& operator<<(ostream&os, vector<t> &v){
        os << "{";
        for(t &i:v){
            os << i << ", ";
        }
        os << "}";
        return os;
    }

    template<class t = long long>
    t in(){
        t res; cin >> res; return res;
    }

    template<class t>
    vector<t> sorted(vector<t> line,function<bool(t,t)> comp=[](t a,t b){return a<b;}){
        sort(line.begin(),line.end(),comp);
        return line;
    }

    template<class t>
    vector<t> reversed(vector<t> line){
        reverse(line.begin(),line.end());
        return line;
    }
    string reversed(string str){
        reverse(str.begin(),str.end());
        return str;
    }

    long long gcd(long long a,long long b){
        while(b){
            a %= b;
            swap(a,b);
        }
        return a;
    }

    long long lcm(long long a,long long b){
        return a / gcd(a,b) * b;
    }

    class output_initializer{
    public:
        output_initializer(){
            ios::sync_with_stdio(false);
            cin.tie(nullptr);
            cout << setprecision(20);
        }
    };output_initializer OUTPUT_INITIALIZER_INSTANCE = output_initializer();
}

using namespace templates;

class Move {
public:
    int x;
    int y;
    int last;
    int next;
    Move(int x=0,int y=0,int last=-1,int next=-1):x(x),y(y),last(last),next(next){}
    bool canMove(int nextDir){
        return (last < 0 or (last - nextDir + 4) % 4 != 2) and
            (next < 0 or next == nextDir);
    }
    Move moved(int nextDir){
        const int dx[] = {1,0,-1,0};
        const int dy[] = {0,1,0,-1};
        return Move(x+dx[nextDir],y+dy[nextDir],nextDir);
    }
    Move withNext(int dir){
        return Move(x,y,last,dir);
    }
    pii position()const{
        return pii(x,y);
    }
};

bool operator<(const Move &a, const Move &b){
    return array<int,4>({a.x,a.y,a.last,a.next}) < array<int,4>({b.x,b.y,b.last,b.next});
}
    

set<pii> func(){
    int n = in();
    int x0 = in();
    int y0 = in();
    int t = in();
    vvvector<int> oks(51,vvector<int>(51,vector<int>(4,false)));
    rep(i,n){
        int x0 = in();
        int y0 = in();
        int x1 = in();
        int y1 = in();
        if(x0>x1)swap(x0,x1);
        if(y0>y1)swap(y0,y1);
        if(y0==y1){
            rep(x,x0,x1+1){
                if(x!=x0)oks[x][y0][2] = true;
                if(x!=x1)oks[x][y0][0] = true;
            }
        }else{
            rep(y,y0,y1+1){
                if(y!=y0)oks[x0][y][3] = true;
                if(y!=y1)oks[x0][y][1] = true;
            }
        }
    }
    method(moved,vector<Move>,Move p){
        vector<Move> res;
        rep(i,4){
            if(not p.canMove(i))continue;
            if(not oks[p.x][p.y][i])continue;
            Move mp = p.moved(i);
            res.emplace_back(mp);
        }
        return res;
    };
    set<Move> current;
    {
        rep(i,4){
            if(oks[x0][y0][i]){
                current.emplace(Move(x0,y0).withNext(i));
            }
        }
    }
    rep(_,t){
        int T = in();
        char D = in<char>();
        int dir;

        set<Move> ncurrent;
        set<pair<Move,int>> used;
        method(movedTimes,void,Move p,int time,int dir){
            method(rec,void,Move p,int t){
                if(t==time){
                    if(p.last==dir){
                        ncurrent.emplace(p);
                    }else if(oks[p.x][p.y][dir] and p.canMove(dir)){
                        ncurrent.emplace(p.withNext(dir));
                    }
                    return;
                }
                if(used.count(make_pair(p,t)))return;
                used.emplace(p,t);
                foreach(np,moved(p)){
                    rec(np,t+1);
                }
            };
            rec(p,0);
        };
        switch(D){
        case 'E':
            dir = 0;
            break;
        case 'N':
            dir = 1;
            break;
        case 'W':
            dir = 2;
            break;
        case 'S':
            dir = 3;
            break;
        }
        foreach(e,current){
            movedTimes(e,T,dir);
        }
        current = ncurrent;
    }
    set<pii> res;
    foreach(i,current)res.emplace(i.position());
    return res;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    foreach(i,func())println(i);
    return 0;
}
accuracy: 1
time_ms: 380
memory_kb: 4344
final_rank: 10

code_snippet: #include "bits/stdc++.h"
using namespace std;

typedef string::const_iterator State;
#define eps 1e-8L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL
#define MOD 998244353LL
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef long double ld;
#define REP(a, b) for (long long(a) = 0; (a) < (b); ++(a))
#define ALL(x) (x).begin(), (x).end()

#define int long long
void solve()
{
  int n, x0, y0, t;
  cin >> n >> x0 >> y0 >> t;
  set<tuple<int, int, int>> cur;
  REP(i, 4)
  {
    cur.insert({x0 * 2, y0 * 2, i});
  }
  set<pair<int, int>> valids;
  REP(i, n)
  {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    a *= 2;
    b *= 2;
    c *= 2;
    d *= 2;
    for (int i = min(a, c); i <= max(a, c); ++i)
    {
      for (int q = min(b, d); q <= max(b, d); ++q)
      {
        valids.insert({i, q});
      }
    }
  }
  REP(i, t)
  {
    int moves;
    string s;
    cin >> moves >> s;
    const int dx[4] = {-1, 0, 1, 0};
    const int dy[4] = {0, -1, 0, 1};
    REP(_, moves)
    {
      set<tuple<int, int, int>> nexts;
      for (auto x : cur)
      {
        REP(t, 4)
        {
          if (t == 2)
            continue;
          int itr = get<2>(x) + t;
          itr %= 4;
          int next_x = get<0>(x) + dx[itr];
          int next_y = get<1>(x) + dy[itr];
          if (valids.count({next_x, next_y}))
          {
            next_x += dx[itr];
            next_y += dy[itr];
            nexts.insert({next_x, next_y, itr});
          }
          if (get<2>(x) >= 4)
            break;
        }
      }
      cur = nexts;
    }
    {
      int expected;
      if (s == "W")
        expected = 0;
      else if (s == "S")
        expected = 1;
      else if (s == "E")
        expected = 2;
      else
        expected = 3;
      set<tuple<int, int, int>> filters;
      for (auto x : cur)
      {
        if (get<2>(x) == expected)
          filters.insert(x);
        REP(t, 4)
        {
          if (t % 2 == 0)
            continue;
          int itr = get<2>(x) + t;
          itr %= 4;
          int next_x = get<0>(x) + dx[itr];
          int next_y = get<1>(x) + dy[itr];
          if (valids.count({next_x, next_y}))
          {
            if (itr == expected)
            {
              filters.insert({get<0>(x), get<1>(x), itr + 4});
            }
          }
        }
      }
      cur = filters;
    }
  }
  set<pair<int, int>> ans;
  for (auto x : cur)
  {
    ans.insert({get<0>(x), get<1>(x)});
  }
  for (auto x : ans)
  {
    cout << x.first / 2 << " " << x.second / 2 << endl;
  }
}
#undef int

// generated by oj-template v4.7.2
// (https://github.com/online-judge-tools/template-generator)
int main()
{
  // Fasterize input/output script
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(100);
  // scanf/printf user should delete this fasterize input/output script

  int t = 1;
  // cin >> t; // comment out if solving multi testcase
  for (int testCase = 1; testCase <= t; ++testCase)
  {
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 3636
final_rank: 9

code_snippet: #include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define Inf 1000000001

vector ok(51,vector(51,vector<bool>(4,false)));
vector<int> dx = {1,0,-1,0},dy = {0,1,0,-1};

vector<pair<pair<int,int>,int>> get(int d,int dir,vector<pair<pair<int,int>,int>> xy){
	vector f(51,vector(51,vector<bool>(4,false)));
	rep(i,xy.size()){
		f[xy[i].first.first][xy[i].first.second][xy[i].second] = true;
	}
	vector<pair<pair<int,int>,int>> ret;
	rep(i,d){
		vector nf(51,vector(51,vector<bool>(4,false)));
		rep(j,51){
			rep(k,51){
				rep(l,4){
					if(f[j][k][l]==false)continue;
					if(ok[j][k][l]==false)continue;
					int x = j+dx[l],y = k+dy[l];
					//cout<<i<<','<<x<<','<<y<<endl;
					rep(ll,4){
						if((l^ll)==2)continue;
						nf[x][y][ll] = true;
						
						if(i==d-1 && (l==dir || ll==dir)){
							ret.emplace_back(make_pair(x,y),ll);
						}
					}
				}
			}
		}
		swap(f,nf);
	}
	return ret;
	
}

int main(){
	
	int n,x0,y0,t;
	cin>>n>>x0>>y0>>t;	
	
	rep(i,n){
		int xs,ys,xe,ye;
		cin>>xs>>ys>>xe>>ye;
		if(xs==xe){
			if(ys>ye)swap(ys,ye);
			for(int j=ys;j<=ye;j++){
				if(j!=ye){
					ok[xs][j][1] = true;
				}
				if(j!=ys){
					ok[xs][j][3] = true;
				}
			}
		}
		else{
			if(xs>xe)swap(xs,xe);
			for(int j=xs;j<=xe;j++){
				if(j!=xe){
					ok[j][ys][0] = true;
				}
				if(j!=xs){
					ok[j][ys][2] = true;
				}
			}
		}
	}
	
	vector<int> d(t),dir(t);
	rep(i,t){
		cin>>d[i];
		char c;
		cin>>c;
		
		if(c=='N')dir[i] = 1;
		if(c=='W')dir[i] = 2;
		if(c=='S')dir[i] = 3;
		if(c=='E')dir[i] = 0;
	}
	
	
	vector<pair<pair<int,int>,int>> xy;
	rep(k,4){
		xy.emplace_back(make_pair(x0,y0),k);
	}
	rep(k,t){
		xy = get(d[k],dir[k],xy);
	}

	vector<pair<int,int>> ans;
	//cout<<xy.size()<<endl;
	rep(i,xy.size()){
		if(ok[xy[i].first.first][xy[i].first.second][xy[i].second]){
			ans.push_back(xy[i].first);
		}
	}
	sort(ans.begin(),ans.end());
	ans.erase(unique(ans.begin(),ans.end()),ans.end());
	//cout<<ans.size()<<endl;
	rep(i,ans.size()){
		cout<<ans[i].first<<' '<<ans[i].second<<endl;
	}
	
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 4044
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int MAX_T = 1005, MAX_C = 55;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
bool dp[MAX_T][MAX_C][MAX_C][4];
bool adv[MAX_C][MAX_C][4];

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, x_0, y_0, t;
    cin >> n >> x_0 >> y_0 >> t;
    for (; n--;) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        if (a == c) {
            if (b > d) swap(b, d);
            for (int i = b; i <= d; i++) {
                if (i != b) adv[a][i][3] = true;
                if (i != d) adv[a][i][1] = true;
            }
        } else {
            if (a > c) swap(a, c);
            for (int i = a; i <= c; i++) {
                if (i != a) adv[i][b][2] = true;
                if (i != c) adv[i][b][0] = true;
            }
        }
    }

    auto ctoi = [](char c) {
        if (c == 'E') return 0;
        if (c == 'N') return 1;
        if (c == 'W') return 2;
        return 3;
    };
    vector<int> way(MAX_T, -1);
    int sum = 0;
    for (; t--;) {
        int d;
        char c;
        cin >> d >> c;
        sum += d;
        way[sum] = ctoi(c);
    }
    for (int l = 0; l < 4; l++) dp[0][x_0][y_0][l] = true;

    for (int i = 0; i < sum; i++) {
        for (int j = 0; j < MAX_C; j++) {
            for (int k = 0; k < MAX_C; k++) {
                for (int l = 0; l < 4; l++) {
                    if (!dp[i][j][k][l]) continue;
                    for (int nl = 0; nl < 4; nl++) {
                        if (!adv[j][k][nl]) continue;                          // able to advance
                        if (~way[i] && l != way[i] && nl != way[i]) continue;  // correct information
                        if ((l ^ nl) == 2) continue;                           // prohibit U-turns
                        int nx = j + dx[nl], ny = k + dy[nl];
                        dp[i + 1][nx][ny][nl] = true;
                    }
                }
            }
        }
    }

    for (int i = 0; i < MAX_C; i++) {
        for (int j = 0; j < MAX_C; j++) {
            bool ok = false;
            for (int k = 0; k < 4; k++) {
                if (dp[sum][i][j][k] && (k == way[sum] || ((k ^ way[sum]) != 2 && adv[i][j][way[sum]]))) {
                    ok = true;
                }
            }
            if (ok) cout << i << ' ' << j << '\n';
        }
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 13220
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
	return (ull)rng() % B;
}

const int N=51;

bool dp[1001][N][N][4];
int ro[N][N][4];
bool ch[1001][4];

// 0:N 1:E 2:S 3:W
int f(char c){
	if(c=='N')return 0;
	else if(c=='E')return 1;
	else if(c=='S')return 2;
	else return 3;
}

int main(){
	cin.tie(nullptr);
	ios::sync_with_stdio(false);
	int n,sx,sy,t; cin >> n >> sx >> sy >> t;
	for(int i=0;i<n;i++){
		int x,y,xx,yy; cin >> x >> y >> xx >> yy;
		if(x==xx){
			if(y>yy)swap(y,yy);
			for(int j=y;j<=yy;j++){
				if(j>y)ro[x][j][2]=1;
				if(j<yy)ro[x][j][0]=1;
			}
		}
		if(y==yy){
			if(x>xx)swap(x,xx);
			for(int j=x;j<=xx;j++){
				if(j>x)ro[j][y][3]=1;
				if(j<xx)ro[j][y][1]=1;
			}
		}
	}
	for(int i=0;i<1001;i++){
		for(int j=0;j<4;j++){
			ch[i][j]=true;
		}
	}
	for(int i=0;i<4;i++){
		dp[0][sx][sy][i]=true;
	}
	int sum=0;
	for(int i=0;i<t;i++){
		int d; cin >> d;
		char c; cin >> c;
		sum+=d;
		for(int j=0;j<4;j++){
			ch[sum][j]=false;
		}
		ch[sum][f(c)]=true;
	}
	for(int i=0;i<sum;i++){
		for(int j=0;j<N;j++){
			for(int k=0;k<N;k++){
				for(int l=0;l<4;l++){
					if(!dp[i][j][k][l])continue;
					if(!ro[j][k][l])continue;
					int x=j,y=k;
					if(l==0)y++;
					else if(l==1)x++;
					else if(l==2)y--;
					else x--;
					if(ch[i+1][l]){
						if(i+1==sum)dp[i+1][x][y][l]=true;
						for(int d=-1;d<=1;d++){
							int nx=(l+d+4)%4;
							if(!ro[x][y][nx])continue;
							dp[i+1][x][y][nx]=true;
						}
					}
					else{
						for(int d=-1;d<=1;d++){
							int nx=(l+d+4)%4;
							if(!ro[x][y][nx])continue;
							if(!ch[i+1][nx])continue;
							dp[i+1][x][y][nx]=true;
							if(i+1==sum)dp[i+1][x][y][l]=true;
						}
					}
				}
			}
		}
	}
	vector<pair<int,int>> res;
	for(int i=0;i<N;i++){
		for(int j=0;j<N;j++){
			for(int k=0;k<4;k++){
				if(ch[sum][k] and dp[sum][i][j][k]){
					res.push_back({i,j});
				}
			}
		}
	}
	for(auto p:res){
		printf("%d %d\n",p.first,p.second);
	}
}
accuracy: 1
time_ms: 10
memory_kb: 9320
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> P;

#define eps 1e-9
#define INF 2000000000              // 2e9
#define LLINF 2000000000000000000ll // 2e18 (llmax:9e18)
#define all(x) (x).begin(), (x).end()
#define sq(x) ((x) * (x))

#define rep(i, x) for (int i = 0; i < (int)(x); i++)
#define drep(i, x) for (int i = ((int)(x)-1); i >= 0; i--)

#define popcount __builtin_popcount
#define next __next
#define prev __prev

#ifndef LOCAL
#define dmp(...) ;
#else
#define dmp(...)                                                               \
  cerr << "[ " << #__VA_ARGS__ << " ] : " << dump_str(__VA_ARGS__) << endl
#endif

// ---------------- Utility ------------------

template <class T>
bool chmin(T &a, const T &b) {
  if (a <= b) return false;
  a = b;
  return true;
}
template <class T>
bool chmax(T &a, const T &b) {
  if (a >= b) return false;
  a = b;
  return true;
}

template <class T>
using MaxHeap = priority_queue<T>;
template <class T>
using MinHeap = priority_queue<T, vector<T>, greater<T>>;

template <class T>
vector<T> vect(int len, T elem) {
  return vector<T>(len, elem);
}

// ----------------- Input -------------------

template <class T, class U>
istream &operator>>(istream &is, pair<T, U> &p) {
  return is >> p.first >> p.second;
}

template <class T>
istream &operator>>(istream &is, vector<T> &vec) {
  for (int i = 0; i < vec.size(); i++) is >> vec[i];
  return is;
}

// ----------------- Output ------------------

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << p.first << ',' << p.second;
}

template <class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (const T &e : v) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const deque<T> &d) {
  for (const T &e : d) os << e << " ";
  return os;
}

template <class T>
ostream &operator<<(ostream &os, const set<T> &s) {
  os << "{ ";
  for (const T &e : s) os << e << " ";
  return os << "}";
}

template <class T, class U>
ostream &operator<<(ostream &os, const map<T, U> &m) {
  os << "{ ";
  for (const auto &[key, val] : m) os << "( " << key << " -> " << val << " ) ";
  return os << "}";
}

template <class TupleTy, size_t... I>
void dump_tuple(ostream &os, const TupleTy t, std::index_sequence<I...>) {
  (..., (os << (I == 0 ? "" : ",") << std::get<I>(t)));
}

template <class... Args>
ostream &operator<<(ostream &os, const tuple<Args...> &t) {
  os << "(";
  dump_tuple(os, t, std::make_index_sequence<sizeof...(Args)>());
  return os << ")";
}

void dump_str_rec(ostringstream &) {}

template <class Head, class... Tail>
void dump_str_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << ", " << head;
  dump_str_rec(oss, forward<Tail>(tail)...);
}

template <class T, class... U>
string dump_str(T &&arg, U &&... args) {
  ostringstream oss;
  oss << arg;
  dump_str_rec(oss, forward<U>(args)...);
  return oss.str();
}

// --------------- Fast I/O ------------------

void fastio() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << fixed << setprecision(20);
}

// ------------ End of template --------------

#define endl "\n"

const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, -1, 0, 1};

bool f[51][51][4];

vector<tuple<int, int, int>> cur;
vector<tuple<int, int, int>> nxt;

bool memo[11][51][51][4];

vector<int> d, dir;

void dfs(int dist, int cx, int cy, int pd, int T) {
  if (memo[dist][cx][cy][pd]) return;
  memo[dist][cx][cy][pd] = true;

  if (dist == d[T]) {
    if (pd != dir[T] && !f[cx][cy][dir[T]]) return;
    if (pd != dir[T] && (dir[T] + 2) % 4 == pd) return;
    nxt.emplace_back(cx, cy, pd);
    return;
  }

  for (int Dir = 0; Dir < 4; Dir++) {
    if ((pd + 2) % 4 == Dir) continue;
    if (dist == 0 && T > 0 && dir[T - 1] != pd && dir[T - 1] != Dir) continue;
    if (!f[cx][cy][Dir]) continue;
    int nx = cx + dx[Dir], ny = cy + dy[Dir];
    assert(!(nx < 0 || nx > 50 || ny < 0 || ny > 50));
    dfs(dist + 1, nx, ny, Dir, T);
  }
}

void solve() {
  int N, x0, y0, t;
  cin >> N >> x0 >> y0 >> t;
  for (int i = 0; i < N; i++) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    if (a == c) {
      for (int j = min(b, d); j < max(b, d); j++) { f[a][j][3] = true; }
      for (int j = min(b, d) + 1; j <= max(b, d); j++) { f[a][j][1] = true; }
    } else {
      for (int j = min(a, c); j < max(a, c); j++) { f[j][b][0] = true; }
      for (int j = min(a, c) + 1; j <= max(a, c); j++) { f[j][b][2] = true; }
    }
  }

  for (int i = 0; i < t; i++) {
    int x;
    char c;
    cin >> x >> c;
    d.push_back(x);
    for (int j = 0; j < 4; j++)
      if ("ESWN"[j] == c) dir.push_back(j);
  }
  assert(d.size() == t && dir.size() == t);

  rep(i, 4) { cur.emplace_back(x0, y0, i); }

  for (int T = 0; T < t; T++) {
    memset(memo, false, sizeof(memo));
    for (auto [x, y, direc] : cur) { dfs(0, x, y, direc, T); }
    swap(cur, nxt);
    nxt.clear();
  }

  vector<P> ans;
  for (auto [x, y, direc] : cur) ans.emplace_back(x, y);
  sort(all(ans));
  ans.erase(unique(all(ans)), ans.end());

  for (auto [x, y] : ans) cout << x << ' ' << y << endl;

  return;
}

int main() {
  fastio();
  solve();
  // int t;
  // cin >> t;
  // while (t--) solve();

  // int t; cin >> t;
  // for(int i=1;i<=t;i++){
  //   cout << "Case #" << i << ": ";
  //   solve();
  // }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3624
final_rank: 4

code_snippet: #line 1 "main.cpp"
#include <iostream>
#include <vector>

using namespace std;

constexpr int X = 51;
constexpr int N = X * X;

int enc(int x, int y) { return x * X + y; }

void solve() {
    int n, x0, y0, t;
    cin >> n >> x0 >> y0 >> t;
    int s = enc(x0, y0);

    auto graph = vector(N, vector(4, -1));
    while (n--) {
        int sx, sy, gx, gy;
        cin >> sx >> sy >> gx >> gy;

        if (sx == gx) {
            int x = sx;
            if (sy > gy) swap(sy, gy);

            for (int y = sy; y < gy; ++y) {
                graph[enc(x, y)][0] = enc(x, y + 1);
                graph[enc(x, y + 1)][2] = enc(x, y);
            }
        } else {
            int y = sy;
            if (sx > gx) swap(sx, gx);

            for (int x = sx; x < gx; ++x) {
                graph[enc(x, y)][1] = enc(x + 1, y);
                graph[enc(x + 1, y)][3] = enc(x, y);
            }
        }
    }

    vector<int> ds{-1};
    while (t--) {
        int d;
        char c;
        cin >> d >> c;

        for (int i = 0; i < d - 1; ++i) {
            ds.push_back(-1);
        }

        int i = 0;
        while (c != "NESW"[i]) ++i;
        ds.push_back(i);
    }

    t = ds.size() - 1;

    auto dp = vector(4, vector(N, false));
    // 直前の移動方向、座標
    for (int d = 0; d < 4; ++d) dp[d][s] = true;

    for (int i = 0; i < t; ++i) {
        int td = ds[i];
        auto ndp = vector(4, vector(N, false));

        for (int v = 0; v < N; ++v) {
            for (int pd = 0; pd < 4; ++pd) {
                if (!dp[pd][v]) continue;

                for (int d = 0; d < 4; ++d) {
                    // Uターン
                    if (abs(d - pd) == 2) continue;
                    // 向き指定
                    if (td != -1 && pd != td && d != td) continue;
                    // 道の存在
                    if (graph[v][d] == -1) continue;

                    ndp[d][graph[v][d]] = true;
                }
            }
        }
        swap(dp, ndp);
    }

    int td = ds.back();
    for (int v = 0; v < N; ++v) {
        bool ok = false;
        for (int d = 0; d < 4; ++d) {
            if (abs(td - d) == 2 || !dp[d][v]) continue;
            if (d == td || graph[v][td] != -1) ok = true;
        }
        if (ok) {
            cout << v / X << " " << v % X << "\n";
        }
    }
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3616
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
//#include <atcoder/segtree>
//using namespace atcoder;

using ll = long long;
using ld = long double;
using pl = pair<ll, ll>;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
#define rep(i,n) for (ll i = 0; i < (n); i++)
#define all(v) (v).begin(), (v).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
#define endl '\n'
#define IOS ios::sync_with_stdio(false); cin.tie(nullptr);
const int inf = 1<<30;
const ll INF = 1ll<<60;
const ll mod = 1000000007;
//const ll mod = 998244353;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }


bool G[1005][1005][4];
bool st[1005][1005][4], nx[1005][1005][4], nx2[1005][1005][4];
ll d[105];
char c[105];
ll n, xx0, yy0, t, ds = 0;

int main() {
    IOS;
    cin >> n >> xx0 >> yy0 >> t;
    rep(i,4) st[xx0+1][yy0+1][i] = true;
    // グラフをつくる
    rep(i,n) {
        ll x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;
        x1++; y1++; x2++; y2++;
        if (x1 == x2) {
            if (y1 > y2) swap(y1, y2); y2 = min(y2, 1001ll);
            for (ll y = y1; y < y2; y++) {
                G[x1][y][1] = true;
                G[x1][y+1][3] = true;
            }
        } else {
            if (x1 > x2) swap(x1, x2); x2 = min(x2, 1001ll);
            for (ll x = x1; x < x2; x++) {
                G[x][y1][0] = true;
                G[x+1][y1][2] = true;
            }
        }
    }
    // 情報の入力
    rep(i,t) {
        cin >> d[i] >> c[i];
        ds += d[i];
    }
    ll id = 0, ds2 = 0, tar = -1; // 今いくつめの情報を処理しているか
    rep(tim,ds) {
        for (int i = 1; i <= 1001; i++) {
            for (int j = 1; j <= 1001; j++) {
                if (st[i][j][0]) {
                    if (G[i][j][0]) nx[i+1][j][0] = 1;
                    if (G[i][j][1]) nx[i][j+1][1] = 1;
                    if (G[i][j][3]) nx[i][j-1][3] = 1;
                }
                if (st[i][j][1]) {
                    if (G[i][j][0]) nx[i+1][j][0] = 1;
                    if (G[i][j][1]) nx[i][j+1][1] = 1;
                    if (G[i][j][2]) nx[i-1][j][2] = 1;
                }
                if (st[i][j][2]) {
                    if (G[i][j][1]) nx[i][j+1][1] = 1;
                    if (G[i][j][2]) nx[i-1][j][2] = 1;
                    if (G[i][j][3]) nx[i][j-1][3] = 1;
                }
                if (st[i][j][3]) {
                    if (G[i][j][0]) nx[i+1][j][0] = 1;
                    if (G[i][j][2]) nx[i-1][j][2] = 1;
                    if (G[i][j][3]) nx[i][j-1][3] = 1;
                }
                if (nx2[i][j][0]) nx[i+1][j][0] = 1;
                if (nx2[i][j][1]) nx[i][j+1][1] = 1;
                if (nx2[i][j][2]) nx[i-1][j][2] = 1;
                if (nx2[i][j][3]) nx[i][j-1][3] = 1;
                /*
                if (tar != -1) {
                    int cnt = 0;
                    if (nx2[i][j][0]) nx[i+1][j][0] = 1;
                    if (nx2[i][j][1]) nx[i][j+1][1] = 1;
                    if (nx2[i][j][2]) nx[i-1][j][2] = 1;
                    if (nx2[i][j][3]) nx[i][j-1][3] = 1;
                    bool ok = 0;
                    rep(k,4) if (nx2[i][j][k]) ok = 1;
                    if (!ok) continue;
                    if (tar == 0 && nx2[i][j][tar]) nx[i+1][j][0] = 1;
                    if (tar == 1 && nx2[i][j][tar]) nx[i][j+1][1] = 1;
                    if (tar == 2 && nx2[i][j][tar]) nx[i-1][j][2] = 1;
                    if (tar == 3 && nx2[i][j][tar]) nx[i][j-1][3] = 1;
                }
                */
            }
        }
        rep(i,1001) rep(j,1001) rep(k,4) {
            st[i+1][j+1][k] = nx[i+1][j+1][k];
            nx[i+1][j+1][k] = 0;
            nx2[i+1][j+1][k] = 0;
        }
        if (tar != -1) tar = -1;
        /*
        rep(k,4) {
            printf("time = %lld, k = %lld\n", tim, k);
            rep(i,10) {
                rep(j,10) cout << st[i+1][j+1][k] << " "; cout << endl;
            } 
        }
        rep(i,10) {
            rep(j,10) {
                bool ruth = 0;
                rep(k,4) if (st[i+1][j+1][k] || nx2[i+1][j+1][k]) ruth = 1;
                if (ruth) cout << "1 ";
                else cout << "0 ";
            }
            cout << endl;
        } cout << endl;
        */

        if (tim+1-ds2 != d[id]) continue;
        // 情報と矛盾するものを排除する、これが難しい
        if (c[id] == 'E') tar = 0;
        if (c[id] == 'N') tar = 1;
        if (c[id] == 'W') tar = 2;
        if (c[id] == 'S') tar = 3;
        ds2 += d[id++];
        //cout << ds2 << endl;
        for (int i = 1; i <= 1001; i++) {
            for (int j = 1; j <= 1001; j++) {
                // 今tarを向いてないならfalseにする
                // 次の移動の始めにtarを向けるやつはnx2に避難させる
                rep(k,4) {
                    if (k != tar) {
                        if ((k+2)%4 != tar && G[i][j][tar] && st[i][j][k]) nx2[i][j][tar] = 1;
                        st[i][j][k] = 0;
                    }
                }
            }
        }
    }
    for (int i = 1; i <= 1001; i++) {
        for (int j = 1; j <= 1001; j++) {
            bool ok = 0; rep(k,4) if (st[i][j][k] || nx2[i][j][k]) ok = 1;
            if (ok) cout << i-1 << " " << j-1 << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 4630
memory_kb: 15200
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
//#include <atcoder/segtree>
//using namespace atcoder;

using ll = long long;
using ld = long double;
using pl = pair<ll, ll>;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
#define rep(i,n) for (ll i = 0; i < (n); i++)
#define all(v) (v).begin(), (v).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
#define endl '\n'
#define IOS ios::sync_with_stdio(false); cin.tie(nullptr);
const int inf = 1<<30;
const ll INF = 1ll<<60;
const ll mod = 1000000007;
//const ll mod = 998244353;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }


bool G[55][55][4];
bool st[55][55][4], nx[55][55][4], nx2[55][55][4];
ll d[105];
char c[105];
ll n, xx0, yy0, t, ds = 0;

int main() {
    //IOS;
    cin >> n >> xx0 >> yy0 >> t;
    rep(i,4) st[xx0+1][yy0+1][i] = true;
    // グラフをつくる
    rep(i,n) {
        ll x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;
        x1++; y1++; x2++; y2++;
        if (x1 == x2) {
            if (y1 > y2) swap(y1, y2); y2 = min(y2, 51ll);
            for (ll y = y1; y < y2; y++) {
                G[x1][y][1] = true;
                G[x1][y+1][3] = true;
            }
        } else {
            if (x1 > x2) swap(x1, x2); x2 = min(x2, 51ll);
            for (ll x = x1; x < x2; x++) {
                G[x][y1][0] = true;
                G[x+1][y1][2] = true;
            }
        }
    }
    // 情報の入力
    rep(i,t) {
        cin >> d[i] >> c[i];
        ds += d[i];
    }
    ll id = 0, ds2 = 0, tar = -1; // 今いくつめの情報を処理しているか
    rep(tim,ds) {
        for (int i = 1; i <= 51; i++) {
            for (int j = 1; j <= 51; j++) {
                if (st[i][j][0]) {
                    if (G[i][j][0]) nx[i+1][j][0] = 1;
                    if (G[i][j][1]) nx[i][j+1][1] = 1;
                    if (G[i][j][3]) nx[i][j-1][3] = 1;
                }
                if (st[i][j][1]) {
                    if (G[i][j][0]) nx[i+1][j][0] = 1;
                    if (G[i][j][1]) nx[i][j+1][1] = 1;
                    if (G[i][j][2]) nx[i-1][j][2] = 1;
                }
                if (st[i][j][2]) {
                    if (G[i][j][1]) nx[i][j+1][1] = 1;
                    if (G[i][j][2]) nx[i-1][j][2] = 1;
                    if (G[i][j][3]) nx[i][j-1][3] = 1;
                }
                if (st[i][j][3]) {
                    if (G[i][j][0]) nx[i+1][j][0] = 1;
                    if (G[i][j][2]) nx[i-1][j][2] = 1;
                    if (G[i][j][3]) nx[i][j-1][3] = 1;
                }
                if (nx2[i][j][0]) nx[i+1][j][0] = 1;
                if (nx2[i][j][1]) nx[i][j+1][1] = 1;
                if (nx2[i][j][2]) nx[i-1][j][2] = 1;
                if (nx2[i][j][3]) nx[i][j-1][3] = 1;
                /*
                if (tar != -1) {
                    int cnt = 0;
                    if (nx2[i][j][0]) nx[i+1][j][0] = 1;
                    if (nx2[i][j][1]) nx[i][j+1][1] = 1;
                    if (nx2[i][j][2]) nx[i-1][j][2] = 1;
                    if (nx2[i][j][3]) nx[i][j-1][3] = 1;
                    bool ok = 0;
                    rep(k,4) if (nx2[i][j][k]) ok = 1;
                    if (!ok) continue;
                    if (tar == 0 && nx2[i][j][tar]) nx[i+1][j][0] = 1;
                    if (tar == 1 && nx2[i][j][tar]) nx[i][j+1][1] = 1;
                    if (tar == 2 && nx2[i][j][tar]) nx[i-1][j][2] = 1;
                    if (tar == 3 && nx2[i][j][tar]) nx[i][j-1][3] = 1;
                }
                */
            }
        }
        rep(i,51) rep(j,51) rep(k,4) {
            st[i+1][j+1][k] = nx[i+1][j+1][k];
            nx[i+1][j+1][k] = 0;
            nx2[i+1][j+1][k] = 0;
        }
        if (tar != -1) tar = -1;
        /*
        rep(k,4) {
            printf("time = %lld, k = %lld\n", tim, k);
            rep(i,10) {
                rep(j,10) cout << st[i+1][j+1][k] << " "; cout << endl;
            } 
        }
        rep(i,10) {
            rep(j,10) {
                bool ruth = 0;
                rep(k,4) if (st[i+1][j+1][k] || nx2[i+1][j+1][k]) ruth = 1;
                if (ruth) cout << "1 ";
                else cout << "0 ";
            }
            cout << endl;
        } cout << endl;
        */

        if (tim+1-ds2 != d[id]) continue;
        // 情報と矛盾するものを排除する、これが難しい
        if (c[id] == 'E') tar = 0;
        if (c[id] == 'N') tar = 1;
        if (c[id] == 'W') tar = 2;
        if (c[id] == 'S') tar = 3;
        ds2 += d[id++];
        //cout << ds2 << endl;
        for (int i = 1; i <= 51; i++) {
            for (int j = 1; j <= 51; j++) {
                // 今tarを向いてないならfalseにする
                // 次の移動の始めにtarを向けるやつはnx2に避難させる
                rep(k,4) {
                    if (k != tar) {
                        if ((k+2)%4 != tar && G[i][j][tar] && st[i][j][k]) nx2[i][j][tar] = 1;
                        st[i][j][k] = 0;
                    }
                }
            }
        }
    }
    for (int i = 1; i <= 51; i++) {
        for (int j = 1; j <= 51; j++) {
            bool ok = 0; rep(k,4) if (st[i][j][k] || nx2[i][j][k]) ok = 1;
            if (ok) cout << i-1 << " " << j-1 << endl;
        }
    }

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3160
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
//#include <atcoder/segtree>
//using namespace atcoder;

using ll = long long;
using ld = long double;
using pl = pair<ll, ll>;
using vl = vector<ll>;
using vvl = vector<vector<ll>>;
#define rep(i,n) for (ll i = 0; i < (n); i++)
#define all(v) (v).begin(), (v).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
#define endl '\n'
#define IOS ios::sync_with_stdio(false); cin.tie(nullptr);
const int inf = 1<<30;
const ll INF = 1ll<<60;
const ll mod = 1000000007;
//const ll mod = 998244353;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }


bool G[1005][1005][4];
bool st[1005][1005][4], nx[1005][1005][4], nx2[1005][1005][4];
ll d[105];
char c[105];
ll n, xx0, yy0, t, ds = 0;

int main() {
    //IOS;
    cin >> n >> xx0 >> yy0 >> t;
    rep(i,4) st[xx0+1][yy0+1][i] = true;
    // グラフをつくる
    rep(i,n) {
        ll x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;
        x1++; y1++; x2++; y2++;
        if (x1 == x2) {
            if (y1 > y2) swap(y1, y2); y2 = min(y2, 1001ll);
            for (ll y = y1; y < y2; y++) {
                G[x1][y][1] = true;
                G[x1][y+1][3] = true;
            }
        } else {
            if (x1 > x2) swap(x1, x2); x2 = min(x2, 1001ll);
            for (ll x = x1; x < x2; x++) {
                G[x][y1][0] = true;
                G[x+1][y1][2] = true;
            }
        }
    }
    // 情報の入力
    rep(i,t) {
        cin >> d[i] >> c[i];
        ds += d[i];
    }
    ll id = 0, ds2 = 0, tar = -1; // 今いくつめの情報を処理しているか
    rep(tim,ds) {
        for (int i = 1; i <= 1001; i++) {
            for (int j = 1; j <= 1001; j++) {
                if (st[i][j][0]) {
                    if (G[i][j][0]) nx[i+1][j][0] = 1;
                    if (G[i][j][1]) nx[i][j+1][1] = 1;
                    if (G[i][j][3]) nx[i][j-1][3] = 1;
                }
                if (st[i][j][1]) {
                    if (G[i][j][0]) nx[i+1][j][0] = 1;
                    if (G[i][j][1]) nx[i][j+1][1] = 1;
                    if (G[i][j][2]) nx[i-1][j][2] = 1;
                }
                if (st[i][j][2]) {
                    if (G[i][j][1]) nx[i][j+1][1] = 1;
                    if (G[i][j][2]) nx[i-1][j][2] = 1;
                    if (G[i][j][3]) nx[i][j-1][3] = 1;
                }
                if (st[i][j][3]) {
                    if (G[i][j][0]) nx[i+1][j][0] = 1;
                    if (G[i][j][2]) nx[i-1][j][2] = 1;
                    if (G[i][j][3]) nx[i][j-1][3] = 1;
                }
                if (nx2[i][j][0]) nx[i+1][j][0] = 1;
                if (nx2[i][j][1]) nx[i][j+1][1] = 1;
                if (nx2[i][j][2]) nx[i-1][j][2] = 1;
                if (nx2[i][j][3]) nx[i][j-1][3] = 1;
                /*
                if (tar != -1) {
                    int cnt = 0;
                    if (nx2[i][j][0]) nx[i+1][j][0] = 1;
                    if (nx2[i][j][1]) nx[i][j+1][1] = 1;
                    if (nx2[i][j][2]) nx[i-1][j][2] = 1;
                    if (nx2[i][j][3]) nx[i][j-1][3] = 1;
                    bool ok = 0;
                    rep(k,4) if (nx2[i][j][k]) ok = 1;
                    if (!ok) continue;
                    if (tar == 0 && nx2[i][j][tar]) nx[i+1][j][0] = 1;
                    if (tar == 1 && nx2[i][j][tar]) nx[i][j+1][1] = 1;
                    if (tar == 2 && nx2[i][j][tar]) nx[i-1][j][2] = 1;
                    if (tar == 3 && nx2[i][j][tar]) nx[i][j-1][3] = 1;
                }
                */
            }
        }
        rep(i,1001) rep(j,1001) rep(k,4) {
            st[i+1][j+1][k] = nx[i+1][j+1][k];
            nx[i+1][j+1][k] = 0;
            nx2[i+1][j+1][k] = 0;
        }
        if (tar != -1) tar = -1;
        /*
        rep(k,4) {
            printf("time = %lld, k = %lld\n", tim, k);
            rep(i,10) {
                rep(j,10) cout << st[i+1][j+1][k] << " "; cout << endl;
            } 
        }
        rep(i,10) {
            rep(j,10) {
                bool ruth = 0;
                rep(k,4) if (st[i+1][j+1][k] || nx2[i+1][j+1][k]) ruth = 1;
                if (ruth) cout << "1 ";
                else cout << "0 ";
            }
            cout << endl;
        } cout << endl;
        */

        if (tim+1-ds2 != d[id]) continue;
        // 情報と矛盾するものを排除する、これが難しい
        if (c[id] == 'E') tar = 0;
        if (c[id] == 'N') tar = 1;
        if (c[id] == 'W') tar = 2;
        if (c[id] == 'S') tar = 3;
        ds2 += d[id++];
        //cout << ds2 << endl;
        for (int i = 1; i <= 1001; i++) {
            for (int j = 1; j <= 1001; j++) {
                // 今tarを向いてないならfalseにする
                // 次の移動の始めにtarを向けるやつはnx2に避難させる
                rep(k,4) {
                    if (k != tar) {
                        if ((k+2)%4 != tar && G[i][j][tar] && st[i][j][k]) nx2[i][j][tar] = 1;
                        st[i][j][k] = 0;
                    }
                }
            }
        }
    }
    for (int i = 1; i <= 1001; i++) {
        for (int j = 1; j <= 1001; j++) {
            bool ok = 0; rep(k,4) if (st[i][j][k] || nx2[i][j][k]) ok = 1;
            if (ok) cout << i-1 << " " << j-1 << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 4440
memory_kb: 15112
final_rank: 18