#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 2096;
const int maxnode = 10000;
int wa[4] = {16,32,64,128};
int va[][2] = {{-1,0},{0,1},{1,0},{0,-1}};
int wode[100];
//舞蹈链的的列头都代表着一个任务
//每一个存在的节点代表的是完成了这个节点所在位置的任务
//然后你要找的是在舞蹈链中寻找一个覆盖,是的每一个列都在这个这个覆盖里面
//而且保证每一个每一个列只被覆盖一次
//建立好舞蹈链(DL)之后用一个回溯的算法,从一个列开始依次选择一个这个列中
//存在的节点,每一个存在的节点代表着这个决策会吧这个任务完成所以其他的同样完
//成这个任务的决策就需要删除,也就是删除这个列
//删除完这一列之后说明已经完成了这个任务,然后向下找下一个任务知道R[0] == 0
//也就是这个链表都变空的时候
//然后开始回溯找其他的方法,这时候就需要回溯啦,
struct DLX{
int n,sz;
int S[maxn];
int row[maxnode],col[maxnode];
int L[maxnode],R[maxnode],U[maxnode],D[maxnode];
int ansd,ans[100],cc;
void init(int n) {
this->n = n;
cc = 0;
for(int i = 0; i <= n; i++) {
U[i] = i; D[i] = i; L[i] = i - 1; R[i] = i + 1;
}
R[n] = 0; L[0] = n;
sz = n+1;
memset(S, 0, sizeof(S));
}
void addRow(int r, vector<int> columns) {
int first = sz;
for(int i = 0; i < columns.size(); i++) {
int c = columns[i];
L[sz] = sz - 1; R[sz] = sz + 1; D[sz] = c; U[sz] = U[c];
D[U[c]] = sz; U[c] = sz;
row[sz] = r; col[sz] = c;
S[c]++; sz++;
}
R[sz-1] = first; L[first] = sz - 1;
}
void remove(int c) {
L[R[c]] = L[c];
R[L[c]] = R[c];
for(int i = D[c]; i != c; i = D[i])
for(int j = R[i]; j != i; j = R[j]) {
U[D[j]] = U[j];
D[U[j]] = D[j];
--S[col[j]];
}
}
void restore(int c) {
for(int i = U[c]; i != c; i = U[i])
for(int j = L[i]; j != i; j = L[j]) {
++S[col[j]];
U[D[j]] = j;
D[U[j]] = j;
}
L[R[c]] = c;
R[L[c]] = c;
}
void dfs(int d){
if(cc > 1) return ;
if(R[0] == 0){
ansd = d;
cc ++;
if(cc > 1) return;
for(int i = 0;i < ansd;i++){
wode[i] = ans[i];
}
return ;
}
int c = R[0];
for(int i = R[0];i != 0;i = R[i]){
if(S[i] < S[c]){
c = i;
}
}
remove(c);
for(int i = D[c]; i != c;i = D[i]){
ans[d] = row[i];
for(int j = R[i]; j != i; j = R[j]) remove(col[j]);
dfs(d+1);
for(int j = L[i]; j != i; j = L[j]) restore(col[j]);
}
restore(c);
}
};
DLX solver;
const int SLOT = 0;
const int ROW = 1;
const int COL = 2;
const int SUB = 3;
int encode(int a,int b,int c){
return a*81+b*9+c+1;
}
void decode(int code,int &a,int &b,int &c){
code --;
c = code%9;
code /= 9;
b = code%9;
code /= 9;
a = code;
}
int puzzle[16][20];
int a[10][10];
int vis[10][10];
struct node{
int x,y;
};
int bfs(int x,int y,int cc){
node u;
u.x = x;
u.y = y;
queue<node> que;
que.push(u);
vis[u.x][u.y] = cc;
while(!que.empty()){
u = que.front();
que.pop();
int c = a[u.x][u.y];
for(int i = 0;i < 4;i++){
if(!(c&wa[i])){
node v;
v.x = u.x + va[i][0];
v.y = u.y + va[i][1];
if(vis[v.x][v.y] < 0){
vis[v.x][v.y] = cc;
que.push(v);
}
}
}
}
}
void read(){
memset(puzzle,0,sizeof(puzzle));
for(int i = 0;i < 9;i++){
for(int j = 0;j < 9; j++){
scanf("%d",&a[i][j]);
puzzle[i][j] = (a[i][j]&(0xf));
}
}
int cc = 1;
memset(vis,-1,sizeof(vis));
for(int i = 0;i < 9;i++){
for(int j = 0;j < 9;j++){
if(vis[i][j]==-1){
bfs(i,j,cc++);
}
}
}
}
int main(){
int kcase = 1;
int t;
scanf("%d",&t);
while(kcase <= t){
read();
solver.init(324);
for(int r = 0;r < 9;r++){
for(int c = 0;c < 9;c++){
for(int v = 1; v <= 9;v++){
if(puzzle[r][c] == v ||puzzle[r][c] == 0){
vector<int> vec;
vec.push_back(encode(SLOT,r,c));
vec.push_back(encode(ROW,r,v-1));
vec.push_back(encode(COL,c,v-1));
vec.push_back(encode(SUB,vis[r][c]-1,v-1));
solver.addRow(encode(r,c,v-1),vec);
}
}
}
}
solver.dfs(0);
printf("Case %d:\n",kcase++);
if(solver.cc == 0){
cout << "No solution" << endl;
}
else if(solver.cc > 1){
cout << "Multiple Solutions" << endl;
}
else{
for(int i = 0;i < solver.ansd;i++){
int r,c,v;
decode(wode[i],r,c,v);
puzzle[r][c] = v;
}
for(int i = 0;i < 9;i++){
for(int j = 0;j < 9;j++){
printf("%d",puzzle[i][j]+1);
}
printf("\n");
}
}
}
return 0;
}
hdu 4069 舞蹈链
最新推荐文章于 2019-03-31 16:38:57 发布