http://acm.hust.edu.cn/vjudge/contest/view.action?cid=65998#problem/F
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=65998#problem/G
bin神專題裏的兩個數獨問題, 後面還有一個變形的數獨(不是普通的九宮格 十六宮格)
這裏一個是九宮格, 一個是十六宮格的數獨…
具體的構圖在前一篇的那裏有說到一位菊苣的blog, 他的介紹寫的非常好, 可以去看一下..
主要是4個約束條件:
- 每一個格子都要放一個數
- 每一行要有9種數字,不許重複
- 每一列要有9種數字,不許重複
- 每一個宮要有9種數字,不許重複
如果是16的就直接把上面改成16..
轉化的和構圖的話, 還是看菊苣的介紹吧..我就重複發明輪子了..
九宮格的: POJ3074
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<iostream>
#define pb push_back
#define INF 0x3f3f3f3f
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
const int mod = 1000000007;
const int N = 9; //3*3數獨
const int MaxN = N*N*N + 10;
const int MaxM = N*N*4 + 10;
const int maxnode = MaxN*4 + MaxM + 10;
char g[MaxN];
struct DLX {
int n,m,size;
int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
int H[MaxN],S[MaxM];
int ansd,ans[MaxN];
void init(int _n,int _m) {
n = _n;
m = _m;
for(int i = 0;i <= m;i++) {
S[i] = 0;
U[i] = D[i] = i;
L[i] = i-1;
R[i] = i+1;
}
R[m] = 0; L[0] = m;
size = m;
for(int i = 1;i <= n;i++)H[i] = -1;
}
void Link(int r,int c) {
++S[Col[++size]=c];
Row[size] = r;
D[size] = D[c];
U[D[c]] = size;
U[size] = c;
D[c] = size;
if(H[r] < 0)H[r] = L[size] = R[size] = size;
else {
R[size] = R[H[r]];
L[R[H[r]]] = size;
L[size] = H[r];
R[H[r]] = size;
}
}
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 resume(int c) {
for(int i = U[c];i != c;i = U[i])
for(int j = L[i];j != i;j = L[j])
++S[Col[U[D[j]]=D[U[j]]=j]];
L[R[c]] = R[L[c]] = c;
}
bool Dance(int d) {
if(R[0] == 0) {
for(int i = 0;i < d;i++)g[(ans[i]-1)/9] = (ans[i]-1)%9 + '1';
for(int i = 0;i < N*N;i++)printf("%c",g[i]);
printf("\n");
return true;
}
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]);
if(Dance(d+1))return true;
for(int j = L[i];j != i;j = L[j])resume(Col[j]);
}
resume(c);
return false;
}
};
inline void get(int &r, int &c1, int &c2, int &c3, int &c4, int i, int j, int k){
r = (i*N+j)*N + k; c1 = i*N + j+1; c2 = N*N+i*N+k;
c3 = N*N*2+j*N+k; c4 = N*N*3+((i/3)*3+(j/3))*N+k;
}
DLX sol;
char s[100];
void solve() {
while(~scanf("%s", s)){
if(!strcmp(s, "end")) return ;
sol.init(N*N*N, N*N*4);
int r, c1, c2, c3, c4;
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
for(int k=1; k<=N; k++) if(s[i*N+j] == '.' || s[i*N+j] == '0' + k){
get(r, c1, c2, c3, c4, i, j, k);
sol.Link(r, c1); sol.Link(r, c2);
sol.Link(r, c3); sol.Link(r, c4);
}
sol.Dance(0);
}
}
int main(void) {
#ifdef DK
freopen("/home/dk/桌面/1.in","r",stdin);
#endif // DK
solve();
return 0;
}
十六宮格的: ZOJ 3122
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<iostream>
#define pb push_back
#define INF 0x3f3f3f3f
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
const int mod = 1000000007;
const int N = 16;
const int MaxN = N*N*N + 10;
const int MaxM = N*N*4 + 10;
const int maxnode = MaxN*4 + MaxM + 10;
char g[MaxN];
struct DLX {
int n,m,size;
int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
int H[MaxN],S[MaxM];
int ansd,ans[MaxN];
void init(int _n,int _m) {
n = _n; m = _m;
for(int i = 0;i <= m;i++) {
S[i] = 0;
U[i] = D[i] = i;
L[i] = i-1;
R[i] = i+1;
}
R[m] = 0; L[0] = m;
size = m;
for(int i = 1;i <= n;i++)H[i] = -1;
}
void Link(int r,int c) {
++S[Col[++size]=c];
Row[size] = r;
D[size] = D[c];
U[D[c]] = size;
U[size] = c;
D[c] = size;
if(H[r] < 0) H[r] = L[size] = R[size] = size;
else {
R[size] = R[H[r]];
L[R[H[r]]] = size;
L[size] = H[r];
R[H[r]] = size;
}
}
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 resume(int c) {
for(int i = U[c];i != c;i = U[i])
for(int j = L[i];j != i;j = L[j])
++S[Col[U[D[j]]=D[U[j]]=j]];
L[R[c]] = R[L[c]] = c;
}
bool Dance(int d) {
//printf("r->%d d : %d\n", R[0], d);
if(R[0] == 0) {
ansd = d;
for(int i = 0; i < d; i++) g[(ans[i]-1)/N] = (ans[i]-1)%N + 'A';
for(int i = 0; i < N; i++) {
for(int j=0; j<N; j++)
printf("%c", g[i*N+j]);
puts("");
}
return true;
}
int c = R[0];
//printf("c : %d down : %d\n", c, D[c]);
for(int i = R[0];i != 0;i = R[i])
if(S[i] < S[c]){
c = i;
//printf("i : %d S[i] : %d\n", i, S[i]);
}
//printf("c : %d down : %d\n", c, D[c]);
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]);
if(Dance(d+1)) return true;
for(int j = L[i];j != i;j = L[j])resume(Col[j]);
}
resume(c);
return false;
}
};
inline void get(int &r, int &c1, int &c2, int &c3, int &c4, int i, int j, int k){
r = (i*N+j)*N + k;
c1 = i*N+j+1;
c2 = N*N+i*N+k;
c3 = N*N*2+j*N+k;
c4 = N*N*3+((i/4)*4+(j/4))*N+k;
}
DLX dlx;
char s[20][100];
inline int read() {
for(int i=0; i<N; i++) if(scanf("%s", s[i]) == EOF)
return false;
//for(int i=0; i<N; i++) printf("%s\n", s[i]);
return true;
}
void solve() {
int first = 1;
while(read()){
if(first) first = 0;
else puts("");
dlx.init(N*N*N, N*N*4);
int r, c1, c2, c3, c4;
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
for(int k=1; k<=N; k++) if(s[i][j] == '-' || s[i][j] == 'A' + k-1){
get(r, c1, c2, c3, c4, i, j, k);
dlx.Link(r, c1); dlx.Link(r, c2);
dlx.Link(r, c3); dlx.Link(r, c4);
//printf("r:%d c1:%d c2:%d c3:%d c4:%d\n", r, c1, c2, c3, c4);
}
dlx.Dance(0);
}
}
int main(void) {
#ifdef DK
freopen("/home/dk/桌面/1.in","r",stdin);
#endif // DK
solve();
return 0;
}