搜尋_常規DFS_位運算_HDOJ5547_Sudoku
Problem DescriptionYi Sima was one of the best counselors of Cao Cao. He likes to play a funny game himself. It looks like the modern Sudoku, but smaller.
InputThe first line of the input gives the number of test cases, T(1≤T≤100) . T test cases follow. Each test case starts with an empty line followed by 4 lines. Each line consist of 4 characters. Each character represents the number in the corresponding cell (one of '1', '2', '3', '4'). '*' represents that number was removed by Yi Sima.
OutputFor each test case, output one line containing Case #x:, where x is the test case number (starting from 1). Then output 4 lines with 4 characters each. indicate the recovered board.
|
思路分析:
使用DFS, 每次選擇可填方案數最少的格子填數即可, 下面給出基於此策略的AC程式碼:
//HDOJ5547_Sudoku
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX = 100, INF = 0x3f3f3f3f;
const int ma[5][5] = {{0, 0, 0, 0, 0}
, {0, 1, 1, 2, 2}
, {0, 1, 1, 2, 2}
, {0, 3, 3, 4, 4}
, {0, 3, 3, 4, 4}};
char G[MAX][MAX];
int R[5], C[5], M[5];//R, C, M分別為行列宮格可選元素
int lowbit(int num){
int res = 0; while(num) num -= num & -num, ++res; return res;
}
//返回可選方案數最少的位置, (0, 0)表示所有數字均已填好, (-1, -1)表示不存在合法位置
pair<int, int> getNex(){
int resx = 0, resy = 0, cnt = INF;
for(int i = 1; i <= 4; ++i)
for(int j = 1; j <= 4; ++j)
if(G[i][j] == '*'){
int y = R[i] & C[j] & M[ma[i][j]], t = lowbit(y);
if(!t) return make_pair(-1, -1);
if(t < cnt) cnt = t, resx = i, resy = j;
}
return make_pair(resx, resy);
}
bool dfs(int x, int y){
int choosn = R[x] & C[y] & M[ma[x][y]];
for(int i = 1; i <= 4; ++i)
if(choosn >> i - 1 & 1){
G[x][y] = '0' + i, R[x] ^= 1 << i - 1, C[y] ^= 1 << i - 1
, M[ma[x][y]] ^= 1 << i - 1;
pair<int, int> nex = getNex();
if(nex.first == -1) return false;
if(!nex.first) return true;
if(dfs(nex.first, nex.second)) return true;
G[x][y] = '*', R[x] ^= 1 << i - 1, C[y] ^= 1 << i - 1
, M[ma[x][y]] ^= 1 << i - 1;
}
return false;
}
int main(){
int T, sn = 0; scanf("%d", &T);
while(++sn, T--){
memset(R, 0x3f, sizeof(R)), memset(C, 0x3f, sizeof(C)), memset(M, 0x3f, sizeof(M));
for(int i = 1; i <= 4; ++i) scanf("%s", G[i] + 1);
for(int i = 1; i <= 4; ++i)
for(int j = 1; j <= 4; ++j)
if(G[i][j] != '*'){
int y = G[i][j] - '0' - 1;
R[i] ^= 1 << y, C[j] ^= 1 << y, M[ma[i][j]] ^= 1 << y;
}
pair<int, int> pos = getNex();
dfs(pos.first, pos.second);
cout << "Case #" << sn << ":" << endl;
for(int i = 1; i <= 4; ++i) cout << &G[i][1] << endl;
}
return 0;
}