【HDU 3909】变种Sudoku 拿个漂亮的当模板吧——dancingLinkx

对于N=2,3,4
分别对于4*4,9*9,16*16的4进制、9进制、16进制
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#define out(v) cout << #v << ": " << (v) << endl
using namespace std;
typedef long long LL;

const int maxN = 20 * 20 * 20, maxM = 4 * 20 * 20;
int N, NN, n;
const int max_size = maxN * maxM;
const int inf = 0x3f3f3f3f;
int L[max_size], R[max_size], U[max_size], D[max_size], CH[max_size], RH[max_size];
int S[maxM], O[maxM];
int head, size;

int node(int up, int down, int left, int right) {
    U[size] = up, D[size] = down;
    L[size] = left, R[size] = right;
    D[up] = U[down] = R[left] = L[right] = size;
    return size++;
}
bool mat[maxN][maxM];
void init(int N, int M) {
    size = 0;
    head = node(0, 0, 0, 0);
    for (int j = 1; j <= M; ++j) {
        CH[j] = node(size, size, L[head], head), S[j] = 0;
    }
    for (int i = 1; i <= N; ++i) {
        int row = -1, k;
        for (int j = 1; j <= M; ++j) {
            if (!mat[i][j]) continue;
            if (row == -1) {
                row = node(U[CH[j]], CH[j], size, size);
                RH[row] = i, CH[row] = CH[j], ++S[j];
            } else {
                k = node(U[CH[j]], CH[j], L[row], row);
                RH[k] = i, CH[k] = CH[j], ++S[j];
            }
        }
    }
}

void remove(const 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[CH[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[CH[j]];
            U[D[j]] = D[U[j]] = j;
        }
    }
    L[R[c]] = R[L[c]] = c;
}
int len;
int anscnt, tar;
bool dfs(const int &k) {
    if (R[head] == head) {
        anscnt++;
        if (anscnt == tar)
        {
            len = k - 1;
            return true;
        }
        else return false;
        //len = k - 1;
        //return true;
    }
    int s = inf, c;
    for (int t = R[head]; t != head; t = R[t]) {
        if (S[t] < s) s = S[t], c = t;
    }
    remove(c);
    for (int i = D[c]; i != c; i = D[i]) {
        O[k] = RH[i];
        for (int j = R[i]; j != i; j = R[j]) {
            remove(CH[j]);
        }
        if (dfs(k + 1)) {
            return true;
        }
        for (int j = L[i]; j != i; j = L[j]) {
            resume(CH[j]);
        }
    }
    resume(c);
    return false;
}

char sudoku[20][20], myans[20][20];
void make()
{
    memset(mat, false, sizeof(mat));
    //const int N = 16, NN = N * N, n = 4;
    for (int i = 1; i <= N; ++i)
        for (int j = 1; j <= N; ++j)
            for (int k = 1; k <= N; ++k)
                if (sudoku[i][j] == '-' || sudoku[i][j] == 'A' + k - 1)
                    mat[(i - 1) * NN + (j - 1) * N + k][(i - 1) * N + j] = true;
    for (int i = 1; i <= N; ++i)
        for (int k = 1; k <= N; ++k)
            for (int j = 1; j <= N; ++j)
                if (sudoku[i][j] == '-' || sudoku[i][j] == 'A' + k - 1)
                    mat[(i - 1) * NN + (j - 1) * N + k][NN + (i - 1) * N + k] = true;
    for (int j = 1; j <= N; ++j)
        for (int k = 1; k <= N; ++k)
            for (int i = 1; i <= N; ++i)
                if (sudoku[i][j] == '-' || sudoku[i][j] == 'A' + k - 1)
                    mat[(i - 1) * NN + (j - 1) * N + k][NN * 2 + (j - 1) * N + k] = true;
    int region;
    for (int i = 1; i <= N; ++i)
        for (int j = 1; j <= N; ++j)
            for (int k = 1; k <= N; ++k) {
                region = ((i - 1) / n) * n + (j - 1) / n + 1;
                if (sudoku[i][j] == '-' || sudoku[i][j] == 'A' + k - 1)
                    mat[(i - 1) * NN + (j - 1) * N + k][NN * 3 + (region - 1) * N + k] = true;
            }
}
char jeo(char x)
{
    if (x == '.' || x == '-') return '-';
    if (x >= '0' && x <= '9') return 'A' + x - '1';
    return 'J' + x - 'A';
}
void output()
{
    for(int i = 1; i <= N; i++)
    {
        for(int j = 1; j <= N; j++)
        {
            if (myans[i][j] <= 'I')
                myans[i][j] = '1' + myans[i][j] - 'A';
            else
            {
                myans[i][j] = 'A' + myans[i][j] - 'J';
            }
            putchar(myans[i][j]);
        }
        putchar('\n');
    }
}
int main()
{
    while(scanf("%d", &n) != EOF)
    {
        N = n * n; NN = N * N;
        for(int i = 1; i <= N; i++)
        {
            scanf("%s", sudoku[i] + 1);
            for(int j = 1; j <= N; j++)
                sudoku[i][j] = jeo(sudoku[i][j]);
        }
        anscnt = 0; tar = 1;
        make();
        init(N * N * N, 4 * N * N);
        dfs(1);
        if (anscnt == 0) printf("No Solution\n");
        else
        {
            for (int i = 1; i <= len; ++i) {
                int x = (O[i] - 1) / NN + 1;
                O[i] -= (x - 1) * NN;
                int y = (O[i] - 1) / N + 1;
                O[i] -= (y - 1) * N;
                int z = O[i];
                myans[x][y] = 'A' + z - 1;
            }
            anscnt = 0; tar = 2;
            make();
            init(N * N * N, 4 * N * N);
            dfs(1);
            if (anscnt == 2) printf("Multiple Solutions\n");
            else
            {
                bool flag = true;
                for(int i = 1; i <= N && flag; i++)
                    for(int j = 1; j <= N && flag; j++)
                        if (sudoku[i][j] != '-')
                        {
                            char tmp = sudoku[i][j];
                            sudoku[i][j] = '-';
                            anscnt = 0; tar = 2;
                            make();
                            init(N * N * N, 4 * N * N);
                            dfs(1);
                            if (anscnt == 1)
                            {
                                flag = false;
                                break;
                            }
                            sudoku[i][j] = tmp;
                        }
                if (!flag) printf("Not Minimal\n");
                else output();
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值