4643 -- 【模擬試題】超級數獨

Description
給一個16*16的方格矩陣,每個方格里填‘A’-‘P’的字符。矩陣裏會有初始的字符。
滿足以下條件:
1. 每一列都出現了‘A’-‘P’的字符。
2. 每一行都出現了‘A’-‘P’的字符。
3. 如下圖,沿着粗線把矩陣分割成16個小矩陣,每一個小矩陣都出現了‘A’-‘P’的字符。

Input
共16行,每行16個字符,由大寫字符‘A’~‘P’以及‘-’構成,‘-’表示待填項。輸入數據保證只有一組解。
Output
輸出數獨字謎的一組解。
Sample Input
–A—-C—–O-I
-J–A-B-P-CGF-H-
–D–F-I-E—-P-
-G-EL-H—-M-J–
—-E—-C–G—
-I–K-GA-B—E-J
D-GP–J-F—-A–
-E—C-B–DP–O-
E–F-M–D–L-K-A
-C——–O-I-L-
H-P-C–F-A–B—
—G-OD—J—-H
K—J—-H-A-P-L
–B–P–E–K–A-
-H–B–K–FI-C–
–F—C–D–H-N-
Sample Output
FPAHMJECNLBDKOGI
OJMIANBDPKCGFLHE
LNDKGFOIJEAHMBPC
BGCELKHPOFIMAJDN
MFHBELPOACKJGNID
CILNKDGAHBMOPEFJ
DOGPIHJMFNLECAKB
JEKAFCNBGIDPLHOM
EBOFPMIJDGHLNKCA
NCJDHBAEKMOFIGLP
HMPLCGKFIAENBDJO
AKIGNODLBPJCEFMH
KDEMJIFNCHGAOPBL
GLBCDPMHEONKJIAF
PHNOBALKMJFIDCEG
IAFJOECGLDPBHMNK
Dancing Links
給程序:

#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<vector>
using namespace std;
const int Slot=0;
const int Row=1;
const int Col=2;
const int Pos=3;
int U[320000],D[320000],L[320000],R[320000],S[1100]; //按理說是應該開4194304=4096*1024的大小,不過既然只有唯一解的話,行數就會相應的小了,開這麼大就夠了 
int ans[300],col[320000],row[320000];//256
char Map[20][20];
char Ans[20][20];
int size=0;
int yama(int a,int b,int c){
    return a*256+b*16+c+1;
}
void jiema(int x,int &a,int &b,int &c){
    x--;
    c=x%16;
    x/=16;
    b=x%16;
    x/=16;
    a=x%16;
}
void init(int n){
    for(int i=0;i<=n;i++){
        L[i]=i-1;R[i]=i+1;U[i]=i;D[i]=i;
    }
    L[0]=n;
    R[n]=0;
    size=n+1;
    memset(S,0,sizeof(S));
}
void ins(int r,vector<int>Q){
    int first=size;
    for(int i=0;i<Q.size();i++){
        int c=Q[i];
        R[size]=size+1;L[size]=size-1;
        U[size]=U[c];D[size]=c;
        D[U[c]]=size;U[c]=size;
        row[size]=r;col[size]=c;
        S[c]++;size++;
    }
    L[first]=size-1;R[size-1]=first;
}
void del(int v){
    for(int i=D[v];i!=v;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]]--;
    }
    R[L[v]]=R[v];
    L[R[v]]=L[v];
}
void restore(int v){
    R[L[v]]=v;
    L[R[v]]=v;
    for(int i=U[v];i!=v;i=U[i])
    for(int j=L[i];j!=i;j=L[j]){
        U[D[j]]=j;
        D[U[j]]=j;
        S[col[j]]++;
    }

}
bool dfs(int d){
    if(R[0]==0){
        return true;
    }
    int c=R[0];
    for(int i=R[0];i!=0;i=R[i])if(S[i]<S[c])c=i;
    del(c);
    for(int i=U[c];i!=c;i=U[i]){
        ans[d]=row[i];
        for(int j=R[i];j!=i;j=R[j])del(col[j]);
        if(dfs(d+1))return true;
        for(int j=L[i];j!=i;j=L[j])restore(col[j]);
    }
    restore(c);
    return false;
}
void print(){
    int a,b,c;
    for(int i=0;i<256;i++){
        jiema(ans[i],a,b,c);
        Ans[a][b]=c+'A';
    }
    for(int i=0;i<16;i++){
    for(int j=0;j<16;j++){
        putchar(Ans[i][j]);
    }
    putchar('\n');
    }
    cout<<endl;
}
int main(){
    while(scanf("%s",Map[0])!=EOF){
    for(int i=1;i<16;i++)
    scanf("%s",Map[i]);
    vector <int>Q;
    init(16*16*4);
    for(int i=0;i<16;i++)
    for(int j=0;j<16;j++)
    for(int k=0;k<16;k++)
    if(Map[i][j]=='-'||Map[i][j]=='A'+k){ 
        Q.clear();
        Q.push_back(yama(Slot,i,j));
        Q.push_back(yama(Row,i,k));
        Q.push_back(yama(Col,j,k));
        Q.push_back(yama(Pos,(i/4)*4+(j/4),k));
        ins(yama(i,j,k),Q);
    }
    if(dfs(0))print();
    }
    return 0;
}

學習了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章