Problem Description
A Pinemi Puzzle is a 10-by-10 array of squares with numbers in some of the squares and the other squares left blank.
To solve the puzzle, add 1, 2, or 3 vertical strokes to each blank box so that:
There are exactly 10 strokes in each row
There are exactly 10 strokes in each column
For each box with a number in it, the number in the box is the total number of strokes in neighboring boxes (up, down, right, left, and diagonal).
For this problem, you will write a program to solve Pinemi Puzzles!
Input
The first line of input contains a single decimal integer P, (1 ≤ P ≤ 100), which is the number of data sets that follow. Each data set should be processed identically and independently.
Each data set consists of 11 lines of input. The first line contains the data set number, K. The following 10 lines each consist of 10 integers separated by spaces. A value of -1 indicates that the box in the puzzle is blank. Otherwise, the value gives the count of neighboring strokes for the box. The ith element of the jth of the 10 input lines describes the box in row j and column i.
Output
For each data set there are 11 lines of output.
The first output line consists of the data set number, K. The following 10 lines of output consist of 10 decimal digits separated by one to six spaces. The value in the jth position in the ith line of the 10 output lines is the input value, if the input value in in the jth position in the ith line was > 0.
Otherwise it is the number of strokes for the (initially blank) box in the jth column in the ith row. Note: For some problems, there may be more than one correct solution. The number of spaces between values is not important, however, padding the numbers out (as shown below in the Sample Output) may make your output more readable and easier to debug.
Sample Input
1
1
-1 9 -1 -1 5 4 -1 5 -1 3
5 -1 -1 -1 8 -1 10 -1 7 -1
2 10 -1 14 -1 -1 -1 -1 9 -1
1 6 -1 -1 -1 12 10 9 -1 -1
-1 8 8 -1 -1 -1 -1 7 -1 -1
-1 -1 6 6 -1 -1 -1 -1 7 4
10 -1 11 -1 9 -1 -1 -1 -1 3
-1 -1 -1 -1 7 5 9 -1 -1 7
-1 9 8 7 -1 6 7 -1 -1 -1
-1 -1 2 -1 -1 -1 -1 6 -1 -1
Sample Output
1
3 9 1 2 5 4 2 5 2 3
5 2 3 1 8 2 10 1 7 1
2 10 2 14 2 1 2 2 9 1
1 6 3 2 1 12 10 9 1 3
1 8 8 1 1 2 3 7 1 1
2 2 6 6 3 1 1 1 7 4
10 2 11 1 9 2 1 2 2 3
1 3 1 2 7 5 9 2 1 7
2 9 8 7 2 6 7 2 2 2
1 1 2 1 1 2 1 6 1 2
Solution
枚举每行相加可能等于10的情况,dfs
核心:1.打表列举可能的情况
2.inline bool next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last)
遗憾的是没能在结束前写完代码。。
AC Code
#include <bits/stdc++.h>
using namespace std;
int board[10][10];
int direction[8][2] = {{-1, -1},
{0, 1},
{1, -1},
{-1, 0},
{1, 0},
{-1, 1},
{0, -1},
{1, 1}};
bool inBound(int x, int y) {
return !(x < 0 || x > 9 || y < 0 || y > 9);
}
int table[11][11][11];
static int stable[11][11][11] = {{{0}, {0}},
{{0}, {0}},
{{0}, {0}},
{{0}, {0}},
{{1, 3, 3, 3}, {2, 2, 3, 3}, {0}},
{{1, 1, 2, 3, 3}, {1, 2, 2, 2, 3}, {2, 2, 2, 2, 2}, {0}},
{{1, 1, 1, 1, 3, 3}, {1, 1, 1, 2, 2, 3}, {1, 1, 2, 2, 2, 2}, {0}},
{{1, 1, 1, 1, 1, 2, 3}, {1, 1, 1, 1, 2, 2, 2}, {0}},
{{1, 1, 1, 1, 1, 1, 1, 3}, {1, 1, 1, 1, 1, 1, 2, 2}, {0}},
{{1, 1, 1, 1, 1, 1, 1, 1, 2}, {0}},
{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {0}}};
int emptyNumOfRow[11];
int strokes[10][10];
void deliver(const int *a, int num, int row) {
int cnt = 0;
for (int i = 0; i < 10; ++i) {
if (board[row][i] == -1)
strokes[row][i] = a[cnt++];
if (cnt >= num)
break;
}
}
bool testRow(int row) {
for (int j = 0; j < 10; ++j) {
if (board[row][j] != -1) {
int sum = 0;
for (auto &dir : direction) {
int dx = dir[0];
int dy = dir[1];
int x = row + dx;
int y = j + dy;
if (inBound(x, y)) {
sum += strokes[x][y];
}
}
if (sum != board[row][j])
return false;
}
}
return true;
}
bool allTest() {
for (int j = 0; j < 10; ++j) {
int sum = 0;
for (auto &stroke : strokes)
sum += stroke[j];
if (sum != 10)
return false;
}
return true;
}
bool dfs(int row) {
if (row == 10) {
if (!testRow(row - 1))
return false;
return allTest();
}
int empNum = emptyNumOfRow[row];
for (int way = 0; way < 3; ++way) {
int tb[11];
memcpy(tb, stable[empNum][way], sizeof(tb));
if (tb[0] == 0)
break;
do {
deliver(tb, empNum, row);
if (row != 0) {
if (!testRow(row - 1))
continue;
}
if (dfs(row + 1))
return true;
} while (next_permutation(tb, tb + empNum));
}
return false;
}
int main() {
int t;
cin >> t;
while (t--) {
int caseNum;
cin >> caseNum;
memcpy(table, stable, sizeof(table));
memset(strokes, 0, sizeof(strokes));
memset(emptyNumOfRow, 0, sizeof(emptyNumOfRow));
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
cin >> board[i][j];
if (board[i][j] == -1)
emptyNumOfRow[i]++;
}
}
dfs(0);
printf("%d\n", caseNum);
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
if (board[i][j] == -1)
printf("%d", strokes[i][j]);
else printf("%d", board[i][j]);
if (j != 9)
putchar(' ');
}
putchar('\n');
}
}
return 0;
}