• POJ 3076 Sudoku


    3076

    思路:

    dfs + 剪枝

    首先,如果这个位置只能填一种字母,那就直接填

    其次,如果对于每一种字母,如果某一列或者某一行或者某一块只能填它,那就填它

    然后,对于某个位置如果不能填字母了,或者某种字母在一行一列或一块中出向了两次以上,说明当前方案不成立

    最后贪心地从可选情况少的往下搜

    代码:

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize(4)
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define fi first
    #define se second
    #define pi acos(-1.0)
    #define LL long long
    //#define mp make_pair
    #define pb push_back
    #define ls rt<<1, l, m
    #define rs rt<<1|1, m+1, r
    #define ULL unsigned LL
    #define pll pair<LL, LL>
    #define pii pair<int, int>
    #define piii pair<pii, int>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
    //head
    
    const int N = 17;
    int mp[N][N];
    int st[N][N];
    int sum = 0;
    char s[N][N+5];
    void add(int x, int y, int t) {
        mp[x][y] = t;
        sum++;
        for (int i = 1; i <= 16; i++) {
            st[i][y] |= 1<<t-1;
            st[x][i] |= 1<<t-1;
        }
        int xx = (x+3)/4, yy = (y+3)/4;
        for (int i = (xx-1)*4 + 1; i <= xx*4; i++) {
            for (int j = (yy-1)*4 + 1; j <= yy*4; j++) {
                st[i][j] |= 1<<t-1;
            }
        }
    }
    void print() {
        for (int i = 1; i <= 16; i++) {
            for (int j = 1; j <= 16; j++) {
                putchar(mp[i][j]-1+'A');
            }
            puts("");
        }
        puts("");
    }
    bool dfs() {
        if(sum == 256) {
            print();
            return true;
        }
    
        for (int i = 1; i <= 16; i++) {
            for (int j = 1; j <= 16; j++) {
                if(!mp[i][j]) {
                    int cnt = 0, t = 0;
                    for (int k = 1; k <= 16; k++) {
                        if((st[i][j] & (1<<k-1)) == 0) {
                            cnt++;
                            t = k;
                            if(cnt == 2) break;
                        }
                    }
                    if(!cnt) return false;
                    if(cnt == 1) add(i, j, t);
                }
            }
        }
    
        for (int i = 1; i <= 16; i++) {
            for (int k = 1; k <= 16; k++) {
                int cnt1 = 0, cnt2 = 0, y;
                for (int j = 1; j <= 16; j++) {
                    if(mp[i][j] == k) cnt1++;
                    if(cnt1 == 2) return false;
                    if(!mp[i][j] && (st[i][j] & (1<<k-1)) == 0) cnt2++, y = j;
                }
                if(!cnt1 && !cnt2) return false;
                if(!cnt1 && cnt2 == 1) add(i, y, k);
            }
        }
    
        for (int j = 1; j <= 16; j++) {
            for (int k = 1; k <= 16; k++) {
                int cnt1 = 0, cnt2 = 0, x;
                for (int i = 1; i <= 16; i++) {
                    if(mp[i][j] == k) cnt1++;
                    if(cnt1 == 2) return false;
                    if(!mp[i][j] && (st[i][j] & (1<<k-1)) == 0) cnt2++, x = i;
                }
                if(!cnt1 && !cnt2) return false;
                if(!cnt1 && cnt2 == 1) add(x, j, k);
            }
        }
    
        for (int i = 1; i <= 16; i++) {
            int x = (i+3)/4, y = i - (x-1)*4;
            for (int k = 1; k <= 16; k++) {
                int cnt1 = 0, cnt2 = 0, xx, yy;
                for (int ii = (x-1)*4+1; ii <= x*4; ii++) {
                    for (int jj = (y-1)*4+1; jj <= y*4; jj++) {
                        if(mp[ii][jj] == k) cnt1++;
                        if(cnt1 == 2) return false;
                        if(!mp[ii][jj] && (st[ii][jj] & (1<<k-1)) == 0) cnt2++, xx = ii, yy = jj;
                    }
                }
                if(!cnt1 && !cnt2) return false;
                if(!cnt1 && cnt2 == 1) add(xx, yy, k);
            }
        }
        if(sum == 256) {
            print();
            return true;
        }
    
        int mn = N, x, y;
        for (int i = 1; i <= 16; i++) {
            for (int j = 1; j <= 16; j++) {
                if(!mp[i][j]) {
                    int cnt = 0;
                    for (int k = 1; k <= 16; k++) {
                        if((st[i][j] & (1<<k-1)) == 0) {
                            cnt++;
                            if(cnt >= mn) break;
                        }
                    }
                    if(cnt < mn) {
                        mn = cnt;
                        x = i;
                        y = j;
                    }
                }
            }
        }
        int tst[N][N], tmp[N][N];
        memcpy(tst, st, sizeof(st));
        memcpy(tmp, mp, sizeof(mp));
        int tsum = sum;
    
        for (int k = 1; k <= 16; k++) {
            if((st[x][y] & (1<<k-1)) == 0) {
                add(x, y, k);
                bool f = dfs();
                if(!f) {
                    memcpy(st, tst, sizeof(tst));
                    memcpy(mp, tmp, sizeof(tmp));
                    sum = tsum;
                }
                else return true;
            }
        }
        return false;
    }
    int main() {
        while(scanf("%s", s[1]+1) != EOF){
            for (int i = 2; i <= 16; i++) {
                scanf("%s", s[i]+1);
            }
            sum = 0;
            mem(mp, 0);
            mem(st, 0);
            for (int i = 1; i <= 16; i++) {
                for (int j = 1; j <= 16; j++) {
                    if(isalpha(s[i][j])) add(i, j, s[i][j] - 'A' + 1);
                }
            }
            dfs();
        }
        return 0;
    }
    /*
    --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-
    */
  • 相关阅读:
    Design Pattern Quick Overview
    [转载]最好的HTML 5编码教程和参考手册分享 .
    业务学习
    [收藏转载]明星软件工程师的十种特质
    一般函数指针和类的成员函数指针
    [LoadRunner]负载测试工具
    [收藏转载]2011 APP年终总结——日均160元的收入经历
    Importance of Side Projects
    [P4 password]Avoiding the Perforce Prompt for Password in Windows
    [收藏转载]我所积累的20条编程经验
  • 原文地址:https://www.cnblogs.com/widsom/p/9516006.html
Copyright © 2020-2023  润新知