#define _CRT_SECURE_NO_WARNINGS 1 #include #include #include #include #include #include #include char N; unsigned long a, b, c, d, e, f; unsigned long _a, _b, _c, _d, _e, _f; char* BOARD = NULL; struct POS { char x; char y; }; std::vector result; POS block_0_0[4] = { {0, 0}, {-1, 0}, {-1, -1}, {0, -1} }; POS block_0_1[4] = { {0, 0}, {0, -1}, {1, -1}, {1, 0} }; POS block_0_2[4] = { {0, 0}, {1, 0}, {1, 1}, {0, 1} }; POS block_0_3[4] = { {0, 0}, {0, 1}, {-1, 1}, {-1, 0} }; POS block_1_0[3] = { {0, 0}, {-1, 0}, {0, -1} }; POS block_1_1[3] = { {0, 0}, {0, -1}, {1, 0} }; POS block_1_2[3] = { {0, 0}, {1, 0}, {0, 1} }; POS block_1_3[3] = { {0, 0}, {-1, 0}, {0, 1} }; POS block_2_0[4] = { {0, 0}, {-1, 0}, {0, -1}, {-2, 0} }; POS block_2_1[4] = { {0, 0}, {0, -1}, {1, 0}, {0, -2} }; POS block_2_2[4] = { {0, 0}, {1, 0}, {0, 1}, {2, 0} }; POS block_2_3[4] = { {0, 0}, {-1, 0}, {0, 1}, {0, 2} }; POS block_3_0[4] = { {0, 0}, {-1, 0}, {-2, 0}, {-3, 0} }; POS block_3_1[4] = { {0, 0}, {0, -1}, {0, -2}, {0, -3} }; POS block_3_2[4] = { {0, 0}, {1, 0}, {2, 0}, {3, 0} }; POS block_3_3[4] = { {0, 0}, {0, 1}, {0, 2}, {0, 3} }; POS block_4_0[4] = { {0, 0}, {0, -1}, {-1, -1}, {0, -2} }; POS block_4_1[4] = { {0, 0}, {1, 0}, {1, -1}, {2, 0} }; POS block_4_2[4] = { {0, 0}, {0, 1}, {1, 1}, {0, 2} }; POS block_4_3[4] = { {0, 0}, {-1, 0}, {-2, 0}, {-1, 1} }; POS* blocks[20] = { block_0_0, block_0_1, block_0_2, block_0_3, block_1_0, block_1_1, block_1_2, block_1_3, block_2_0, block_2_1, block_2_2, block_2_3, block_3_0, block_3_1, block_3_2, block_3_3, block_4_0, block_4_1, block_4_2, block_4_3 }; char blockSize[20] = { 4, 4, 4, 4, 3, 3, 3, 3,4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }; int tempBlock[4]; char removeRows[25]; char removeCols[25]; void reset() { result.clear(); a = _a; b = _b; c = _c; d = _d; e = _e; f = _f; if (BOARD == NULL) BOARD = (char*)malloc(N * N); memset(BOARD, 0, N * N); } bool load(const char* fileName) { char tempBuffer[100]; FILE* in; in = fopen(fileName, "r"); if (in == NULL) return false; if (fgets(tempBuffer, 100, in)) { sscanf(tempBuffer, "%d %lu %lu %lu %lu %lu %lu", &N, &_a, &_b, &_c, &_d, &_e, &_f); } return true; } inline char getNextBlock() { c = (c ^ a) + b; f = (f ^ d) + e; char blockNum = c % 5; char blockRot = f % 4; return blockNum * 4 + blockRot; } inline void checkLines(int &totalCompleteRows, int& totalCompleteColumns) { //calculate if row is complete for (int yyy = 0; yyy < N; yyy++) { bool lineComplete = true; for (int xxx = 0; xxx < N; xxx++) { if (BOARD[yyy * N + xxx] == 0) { lineComplete = false; break; } } if (lineComplete) { removeRows[totalCompleteRows] = yyy; totalCompleteRows++; } } //calculate if column is complete for (int xxx = 0; xxx < N; xxx++) { bool lineComplete = true; for (int yyy = 0; yyy < N; yyy++) { if (BOARD[yyy * N + xxx] == 0) { lineComplete = false; break; } } if (lineComplete) { removeCols[totalCompleteColumns] = xxx; totalCompleteColumns++; } } } bool move(int V, int lineV, bool bExtra) { char bIdx = getNextBlock(); POS* myBlock = blocks[bIdx]; char myBlockSize = blockSize[bIdx]; int bestScore = -1; POS bestPos; for (char x = 0; x < N; x++) { for (char y = 0; y < N; y++) { bool canPlace = true; for (char i = 0; i < myBlockSize; i++) { char newX = x + myBlock[i].x; char newY = y + myBlock[i].y; if (newX < 0 || newX >= N || newY < 0 || newY >= N || BOARD[newY * N + newX] == 1) { canPlace = false; break; } } if (canPlace) { for (char i = 0; i < myBlockSize; i++) { char newX = x + myBlock[i].x; char newY = y + myBlock[i].y; tempBlock[i] = newY * N + newX; BOARD[tempBlock[i]] = 1; } int totalCompleteRows = 0; int totalCompleteColumns = 0; checkLines(totalCompleteRows, totalCompleteColumns); int calcScore = (totalCompleteRows * totalCompleteRows + totalCompleteColumns * totalCompleteColumns) * lineV; int extraScore = 0; for (char i = 0; i < myBlockSize; i++) { char newX = x + myBlock[i].x; char newY = y + myBlock[i].y; int score = 0; if (newY > 0 && BOARD[(newY - 1) * N + newX] == 1) score+= V; if (newY < N - 1 && BOARD[(newY + 1) * N + newX] == 1) score+= V; if (newX > 0 && BOARD[newY * N + newX - 1] == 1) score+= V; if (newX < N - 1 && BOARD[newY * N + newX + 1] == 1) score+= V; if (bExtra) { if (newX == 0 || newX == N - 1) score+= V>>1; if (newY == 0 || newY == N - 1) score+= V>>1; } else { if (newX == 0 || newX == N - 1) score+= V; if (newY == 0 || newY == N - 1) score+= V; } calcScore += score; if (newY > 0 && newX > 0 && BOARD[(newY - 1) * N + newX - 1] == 1) extraScore++; if (newY < N - 1 && newX < N - 1 && BOARD[(newY + 1) * N + newX + 1] == 1) extraScore++; if (newY > 0 && newX < N - 1 && BOARD[(newY - 1) * N + newX + 1] == 1) extraScore++; if (newY < N - 1 && newX>0 && BOARD[(newY + 1) * N + newX - 1] == 1) extraScore++; calcScore += extraScore; } if (bestScore < calcScore) { bestScore = calcScore; bestPos.x = x; bestPos.y = y; } //remove block from tempBlock for (char i = 0; i < myBlockSize; i++) { BOARD[tempBlock[i]] = 0; } } } } if (bestScore >= 0) { result.push_back(bestPos); for (char i = 0; i < myBlockSize; i++) { char newX = bestPos.x + myBlock[i].x; char newY = bestPos.y + myBlock[i].y; BOARD[newY * N + newX] = 1; } //remove complete rows and columns int totalRemoveRows = 0; int totalRemoveCols = 0; checkLines(totalRemoveRows, totalRemoveCols); if (totalRemoveRows > 0) { for (char i = 0; i < totalRemoveRows; i++) { for (char xxx = 0; xxx < N; xxx++) { BOARD[removeRows[i] * N + xxx] = 0; } } } if (totalRemoveCols > 0) { for (char i = 0; i < totalRemoveCols; i++) { for (char yyy = 0; yyy < N; yyy++) { BOARD[yyy * N + removeCols[i]] = 0; } } } } return bestScore >= 0; } void save(const char* fileName) { FILE* out; out = fopen(fileName, "w"); fprintf(out, "%ld\n", result.size()); for (long long unsigned int z = 0; z < result.size(); z++) { fprintf(out, "%d %d\n", result[z].y + 1, result[z].x + 1); } fclose(out); } void solve() { std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); int bestMoves = 0; load("block.in"); for (int lineV = 100; lineV >= 30; lineV--) { for (int e = 1; e >= 0; e--) { for (int V = 8; V <= 30; V++) { reset(); while (move(V, lineV, e)) { std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); long et = std::chrono::duration_cast(end - begin).count(); if (et > 5000) return; } if (bestMoves < result.size()) { bestMoves = result.size(); save("block.out"); } } } } //std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); //long et = std::chrono::duration_cast(end - begin).count(); //printf("Best result %d (%d ms)\n",bestMoves, et); } int main(int argc, char* argv[]) { solve(); free(BOARD); return 0; }