Algoritmul, pas cu pas
C1: simulez direct — aplic translația, apoi rotesc tot punctul curent (: etc.). .
Observația cheie (C2/C3). Poziția finală , unde și e vectorul translației . Cum cu liber în , fiecare poate fi orice multiplu de , independent. Rotind un vector unitar cu multipli de obțin toate cele 4 direcții, deci fiecare translație poate ajunge în orice direcție. Ținta devine o sumă de vectori unitari liber aleși.
C2: DA și (distanță Manhattan și paritate).
C3: aleg direcțiile ( spre , spre , restul în perechi care se anulează), aflu care duce în , apoi recuperez (cu ).
Soluția în C++
#include <fstream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
ifstream fin("rotatii.in");
ofstream fout("rotatii.out");
pair<int,int> trvec(char c) {
if (c == 'N') return {0, 1};
if (c == 'S') return {0, -1};
if (c == 'E') return {1, 0};
return {-1, 0};
}
pair<int,int> rotv(pair<int,int> p, int deg) {
int x = p.first, y = p.second;
if (deg == 0) return {x, y};
if (deg == 90) return {y, -x};
if (deg == 180) return {-x, -y};
return {-y, x};
}
int main() {
int C; fin >> C;
if (C == 1) {
int N; string tr; fin >> N >> tr;
vector<int> rots(N);
for (auto &x : rots) fin >> x;
long long x = 0, y = 0;
for (int i = 0; i < N; i++) {
auto t = trvec(tr[i]); x += t.first; y += t.second;
auto r = rotv({(int)x, (int)y}, rots[i]); x = r.first; y = r.second; // rotim întreg punctul
}
fout << x << " " << y << "\n";
} else if (C == 2) {
int T; fin >> T;
while (T--) {
int N; string tr; long long a, b;
fin >> N >> tr >> a >> b;
long long man = llabs(a) + llabs(b);
fout << ((man <= N && (man % 2) == (N % 2)) ? "DA" : "NU") << "\n";
}
} else { // C == 3
int N; string tr; long long a, b;
fin >> N >> tr >> a >> b;
vector<pair<int,int>> d;
for (long long k = 0; k < llabs(a); k++) d.push_back({a > 0 ? 1 : -1, 0});
for (long long k = 0; k < llabs(b); k++) d.push_back({0, b > 0 ? 1 : -1});
long long man = llabs(a) + llabs(b);
for (long long k = 0; k < (N - man) / 2; k++) { d.push_back({1, 0}); d.push_back({-1, 0}); }
vector<int> c(N);
for (int i = 0; i < N; i++) {
auto t = trvec(tr[i]);
for (int deg : {0, 90, 180, 270}) if (rotv(t, deg) == d[i]) { c[i] = deg; break; }
}
int cnext = 0;
vector<int> rots(N);
for (int i = N - 1; i >= 0; i--) { rots[i] = ((c[i] - cnext) % 360 + 360) % 360; cnext = c[i]; }
for (int i = 0; i < N; i++) fout << rots[i] << (i < N - 1 ? " " : "\n");
}
return 0;
}- Crezi că rotația mișcă doar ultimul pas — rotația aplică transformarea întregului punct curent în jurul originii.
- Verifici doar distanța Manhattan, fără paritate — fiecare pas schimbă cu paritatea lui ; ai nevoie de .
- La C3 uiți pașii care se anulează — completează până la pași cu perechi opuse, altfel paritatea/numărul nu se potrivesc.