#include using namespace std; const int maxN = 2e4+10; #define pb push_back const long long b1 = 61; const long long b2 = 37; const long long mo1 = 1e9+7; const long long mo2 = 1e9 + 9; const double iterConst1 = 3.4; const double iterConst2 = 3.5 ; const double iterConst3 = 0.0; const int square = 8; vector res[maxN], curRes[maxN]; string word[maxN]; int bestAns = 1e6; int bestX, bestY, curX, curY; vector, string>> moves, curMoves; int subtask, n; int startX, startY; mt19937 rng(time(0)); pair sortedWords[maxN]; vector> previousMoves; clock_t startTime; int dist[100][100][100]; pair pre[100][100][100]; int sumLen = 0; int badMode[maxN]; int solve2Res; int lastRow; void read_data() { freopen("crossword.in", "r", stdin); cin>>subtask; cin>>n; sumLen = 0; for (int i=0; i>word[i]; sumLen +=word[i].size(); } fclose(stdin); } int initializer() { for (int i=0; i=0 && x=0 && y0) return 'R'; if (y<0) return 'L'; if (x>0) return 'D'; return 'U'; } int finder(int x, int y, string &s, int idx) { if (idx == s.size() - 1) return idx + 1; if (inside(x, y + 1) && curRes[x][y + 1] == s[idx + 1]) return finder(x, y+1, s, idx+1); if (inside(x, y-1) && curRes[x][y-1] == s[idx + 1]) return finder(x, y-1, s, idx+1); return idx + 1 ; } int pref(string &s, string &t) { int sz1 = s.size(); int sz2 = t.size(); long long hs11 = 0; long long hs12 = 0; long long hs21 = 0; long long hs22 = 0; long long curb1 = 1; long long curb2 = 1; int ans = 0; for (int i=0; ilen) { len = len1; poc = j; } } } reverse(sortedWords[i].first.begin(), sortedWords[i].first.end()); currentString = ""; for (int j = previousMoves.size() - sortedWords[i-1].first.size(); j < previousMoves.size(); j++) { int poz = j - previousMoves.size() + sortedWords[i-1].first.size(); currentString+= sortedWords[i-1].first[poz]; if (j == previousMoves.size() -1 || previousMoves[j].first == startX) { int len1 = pref(currentString, sortedWords[i].first); if (len1>len) { len = len1; poc = j; reversedMode = 1; } } } if (!reversedMode) reverse(sortedWords[i].first.begin(), sortedWords[i].first.end()); string s = ""; if (len == 0) { previousMoves.pb({pozX, pozY}); curMoves[sortedWords[i].second] = {{pozX, pozY}, ""}; coverFrom(pozX, pozY, sortedWords[i].first, 0, sortedWords[i].second, 1); continue; } for (int j = len-1; j < sortedWords[i].first.size(); j++) s+=sortedWords[i].first[j]; pozX = previousMoves[poc].first; pozY = previousMoves[poc].second; curMoves[sortedWords[i].second] = {{previousMoves[poc - len + 1].first, previousMoves[poc - len + 1].second}, ""}; for (int j = poc - len + 1 ; j<=poc; j++) previousMoves.pb(previousMoves[j]); for (int j = poc - len +2 ; j<= poc; j++) { int xi1 = previousMoves[j-1].first; int yi1 = previousMoves[j-1].second; int xi2 = previousMoves[j].first; int yi2 = previousMoves[j].second; curMoves[sortedWords[i].second].second+=from_to(xi2 - xi1, yi2 - yi1); } coverFrom(pozX, pozY, s, 0, sortedWords[i].second, 1); } if (reversedMode) { int idx = sortedWords[i].second; badMode[i] = 1; int trenX = curMoves[idx].first.first; int trenY = curMoves[idx].first.second; for (auto j = 0; j< curMoves[idx].second.size(); j++) { if (curMoves[idx].second[j] =='L') { curMoves[idx].second[j] = 'R'; trenY--; } else if (curMoves[idx].second[j] == 'R') { curMoves[idx].second[j] = 'L'; trenY++; } else if (curMoves[idx].second[j] =='U') { curMoves[idx].second[j] = 'D'; trenX--; } else if (curMoves[idx].second[j] == 'D') { curMoves[idx].second[j] = 'U'; trenX++; } } if (curMoves[idx].second.size()) reverse(curMoves[idx].second.begin(), curMoves[idx].second.end()); curMoves[idx].first = {trenX, trenY}; } } int curScore = calcScore(); if (curScore < bestAns) replaceBest(); for (int i=0; i