两个题都是数独,题意很明确。
建图的思路大神写的很好:
行:一共9 * 9 * 9 == 729行。一共9 * 9小格,每一格有9种可能性(1 - 9), 每一种可能都对应着一行。
列:一共(9 + 9 + 9) * 9 + 81 == 324 种前面三个9分别代表着9行9列和9小 块。乘以9的意思是9种可能,因为每种可能只可以选择一个。81代表着81个 小格,限制着每一个小格只可以放一个地方。
我个人的理解是行就是所有的可能,列就是限制条件,这里就是列
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <vector> #include <set> #include <string> using namespace std; #define For(i,a) for(i=0;i<a;i++) #define Foru(i,a,b) for(i=a;i<=b;i++) #define Ford(i,a,b) for(i=a;i>=b;i--) #define clr(ar,vel) memset(ar,vel,sizeof(ar)) #define PB push_back #define maxint 0x7fffffff int ans[300]; string s; const int maxn = 502011; const int head = 0; int size; int col[maxn]; int row[maxn]; int cell[maxn]; int R[maxn], L[maxn], U[maxn], D[maxn]; int S[maxn], C[maxn], O[maxn], H[maxn], X[maxn]; void remove(const int &c) { //cout << "remove " << c << endl; //remove column c and all row i that A[i][c] == 1 L[R[c]] = L[c]; R[L[c]] = R[c]; //remove column c; for (int i = D[c]; i != c; i = D[i]) { //remove i that A[i][c] == 1 for (int j = R[i]; j != i; j = R[j]) { //cout << "remove" << endl; U[D[j]] = U[j]; D[U[j]] = D[j]; --S[C[j]]; //decrease the count of column C[j]; } } } void resume(const int &c) { for (int i = U[c]; i != c; i = U[i]) { for (int j = L[i]; j != i; j = L[j]) { ++S[C[j]]; U[D[j]] = j; D[U[j]] = j; } } L[R[c]] = c; R[L[c]] = c; } bool dfs(const int &k) { if (R[head] == head) { //One of the answers has been found. //cout << "answer " << k << endl; for(int i = 0; i < k; i ++){ int num, pos; num = X[O[i]]/256; pos = X[O[i]]%256; s[pos] = num+'A'-1; //cout << num << ' ' << pos << endl; } for(int i = 0; i < 16; i ++) { for(int j = 0; j < 16; j ++){ cout << s[i*16+j]; } cout << endl; } return true; } int s(maxint), c; for (int t = R[head]; t != head; t = R[t]) { //select the column c which has the fewest number of element. if (S[t] < s) { s = S[t]; c = t; } } //cout << k << endl; remove(c); for (int i = D[c]; i != c; i = D[i]) { O[k] = i; //record the answer. for (int j = R[i]; j != i; j = R[j]) { remove(C[j]); } if (dfs(k + 1)) {return true;} for (int j = L[i]; j != i; j = L[j]) { resume(C[j]); } } resume(c); return false; } void link(int r,int c) { ++S[C[size]=c]; 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; } X[size++]=r; } void init(int m){ clr(col,0); clr(row,0); clr(cell,0); clr(ans, -1); clr(H, -1); for(int i = 0; i <= m; i ++){ S[i] = 0; R[i] = i+1; L[i+1] = i; U[i] = D[i] = i; } R[m] = 0; L[0] = m; size = m+1; } int main(){ int rownum; int c1, c2, c3, c4; char str[20]; int flag = 0; while(~scanf("%s",str)){ if(flag) cout << endl; flag = 1; s = str; for(int i = 1; i < 16; i ++) { scanf("%s",str); s+= str; } //cout << s << endl; init(1024); rownum = 1; int cnt = 0; //for(int i = 0; i < 10; i ++) cout << ans[i] << ' ';cout << endl; for(int i = 1; i <= 16; i ++){ for(int j = 1; j <= 16; j ++){ if(s[cnt] != '-'){ int w = s[cnt] - 'A'+1; ans[cnt] = w; // cout << w << endl; chance(i, j, w, rownum, c1, c2, c3, c4); link(rownum,c1); link(rownum,c2); link(rownum,c3); link(rownum,c4); // cout << c1 << ' ' << c2 << ' ' << c3 << ' ' << c4 << endl; //system("pause"); row[c1] = 1; col[c2] = 1; cell[c3] = 1; } cnt++; } } //for(int i = 0; i < 10; i ++) cout << ans[i] << ' ';cout << endl; //for(int i = 0; i < 324; i ++) cout << S[i] << ' ' ;cout << endl; for(int i = 1; i <= 16; i ++){ for(int j = 1; j <= 16; j ++){ if( ans[i*16-16+j-1] == -1){ for(int w = 1; w <= 16; w ++){ chance(i, j, w, rownum, c1, c2, c3, c4); if( row[c1] || col[c2] || cell[c3] ) continue; link(rownum,c1); link(rownum,c2); link(rownum,c3); link(rownum,c4); // cout << c4 << endl; } //rownum++; } } } dfs(0); //cout << "answer" << endl; } return 0; }