zoukankan      html  css  js  c++  java
  • hdu 4069 垃圾数独

    首先dfs给每个格子分一个大的区块

    其次套板子就a

    我一开始直接在选取行的时候填数独,发现超时

    我这一行也就4个元素,找到 x <= 81 的列计算元素位置,81 < x <= 162 的列计算是什么数字

    这就超时了? 

    后来还是记录每一行的代表的  行和列 和 数字

    选区行的时候记录选取的行

    最后矩阵为空的时候  一起填入数独

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    //精确覆盖问题的定义:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1
    const int MN = 1005;//最大行数
    const int MM = 1005;//最大列数
    const int MNN = 1e5+5; //最大点数
    int pl;
    int anss[15][15];
    struct node
    {
        int i,j,val;
    };
    node p[9*9*9+10];
    struct DLX
    {
        int n, m, si;//n行数m列数si目前有的节点数
        //十字链表组成部分
        int U[MNN], D[MNN], L[MNN], R[MNN], Row[MNN], Col[MNN];
        //第i个结点的U向上指针D下L左R右,所在位置Row行Col列
        int H[MN], S[MM]; //记录行的选择情况和列的覆盖情况
        int ansd, ans[MN];
        int k = 0;
        void init(int _n, int _m)  //初始化空表
        {
            n = _n;
            m = _m;
            k = 0;
            for (int i = 0; i <= m; i++) //初始化第一横行(表头)
            {
                U[i] = D[i] = i;      //目前纵向的链是空的
                L[i] = i - 1;
                R[i] = i + 1;         //横向的连起来
            }
            R[m] = 0; L[0] = m;
            si = m;                 //目前用了前0~m个结点
            memset(S, 0, sizeof(S));
            memset(H, -1, sizeof(H));
        }
        void link(int r, int c)    //插入点(r,c)
        {
            ++S[Col[++si] = c];     //si++;Col[si]=c;S[c]++;
            Row[si] = r;//si该结点的行数为r
            D[si] = D[c];//向下指向c的下面的第一个结点
            U[D[c]] = si;//c的下面的第一个结点的上面为si
            U[si] = c;//si的上面为列指针
            D[c] = si;//列指针指向的第一个该列中的元素设为si
            if (H[r]<0)//如果第r行没有元素
                H[r] = L[si] = R[si] = si;
            else
            {
                R[si] = R[H[r]];//si的右边为行指针所指的右边第一个元素
                L[R[H[r]]] = si;//行指针所指的右边第一个元素的左侧为si
                L[si] = H[r];//si的左侧为行指针
                R[H[r]] = si;//行指针的右侧为si
            }
        }
        void rm(int c)        //列表中删掉c列
        {
            L[R[c]] = L[c];//表头操作  //c列头指针的右边的元素的左侧指向c列头指针左边的元素
            R[L[c]] = R[c];//c列头指针的左边的元素的右侧指向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)        //恢复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]];//D[U[j]]=j;U[D[j]]=j;S[Col[j]]++;
            L[R[c]] = R[L[c]] = c;//c列头指针左右相连
        }
        bool dance(int d) //选取了d行
        {
            if (ansd != -1 && ansd < d)return 0;
            if (R[0] == 0)//全部覆盖了
            {
                k++;
                //全覆盖了之后的操作
                if(ansd==-1)ansd = d;
                else if (d < ansd) ansd = d;
                /*memcpy(fina,anss,sizeof(anss));
                for(int i = 0; i < 9; ++i)
                {
                    for(int j = 0; j < 9; ++j)
                        printf("%d",anss[i][j]);
                    printf("
    ");
                }*/
                for(int i = 0; i < ansd; ++i)
                {
                    anss[p[ans[i]].i][p[ans[i]].j] = p[ans[i]].val;
                }
                return 1;
            }
            int c = R[0];//表头结点指向的第一个列
            for (int i = R[0]; i != 0; i = R[i])//枚举列头指针
                if (S[i]<S[c])//找到列中元素个数最少的
                    c = i;
            rm(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])
                    rm(Col[j]);//将该列的某个元素的行上的元素所在的列都删去
                dance(d + 1);
                if(k == 2 ) return 1;
                for (int j = L[i]; j != i; j = L[j])
                    resume(Col[j]);
    
            }
            resume(c);
            return 0;
        }
    };
    int s[20][20];
    int kua[20][20];
    int arr[20][20];
    int dx[4] = {0,1,0,-1};
    int dy[4] = {-1,0,1,0};
    int fc[4] = {128,64,32,16};
    DLX di;
    void dfs(int x,int y,int cnt);
    int main()
    {
        int t,ppap = 1;
        scanf("%d",&t);
        while(ppap <= t)
        {
            memset(anss,0,sizeof(anss));
            for(int i = 0; i < 9; ++i)
            {
                for(int j = 0; j < 9; ++j)
                {
                    scanf("%d",s[i]+j);
                }
            }
            int cnt = 1;
            memset(kua,0,sizeof(kua));
            for(int i = 0; i < 9; ++i)
                for(int j = 0; j < 9; ++j)
                {
                    if(kua[i][j] == 0)
                    {
                        kua[i][j] = cnt;
                        dfs(i,j,cnt++);
                    }
                }
            /*
            for(int i = 0; i < 9; ++i)
            {
                for(int j = 0; j < 9; ++j)
                    printf("%d ",arr[i][j]);
                printf("
    ");
            }
            */
            //----------------------------
            di.init(9*9*9,9*9*4);
            for(int i = 0; i < 9; ++i)
            {
                for(int j = 0; j < 9; ++j)
                {
                    //cout << s[cnt];
                    if(arr[i][j] == 0)
                    {
                        for(int d = 1; d <= 9; ++d)
                        {
                            di.link(i*9*9+j*9+d,i*9+j+1);
                            di.link(i*9*9+j*9+d,i*9+d+81);
                            di.link(i*9*9+j*9+d,j*9+d+162);
                            di.link(i*9*9+j*9+d,(kua[i][j]-1)*9+d+243);
                            p[i*9*9+j*9+d].i = i; p[i*9*9+j*9+d].j = j; p[i*9*9+j*9+d].val = d;
                        }
                    }
                    else
                    {
                        int d = arr[i][j];
                        di.link(i*9*9+j*9+d,i*9+j+1);
                        di.link(i*9*9+j*9+d,i*9+d+81);
                        di.link(i*9*9+j*9+d,j*9+d+162);
                        di.link(i*9*9+j*9+d,(kua[i][j]-1)*9+d+243);
                        p[i*9*9+j*9+d].i = i; p[i*9*9+j*9+d].j = j; p[i*9*9+j*9+d].val = d;
                    }
                }
            }
    
            di.ansd = -1;
            di.dance(0);
            printf("Case %d:
    ",ppap++);
            if(di.ansd == -1)
            {
                printf("No solution
    ");
                continue;
            }
            if(di.k != 1)
            {
                printf("Multiple Solutions
    ");
                continue;
            }
            /*for(int i = 0; i < 9; ++i)
            {
                for(int j = 0; j < 9; ++j)
                    printf("%d",anss[i][j]);
                printf("
    ");
            }*/
            for(int i = 0; i < 9; ++i)
            {
                for(int j = 0; j < 9; ++j)
                {
                    printf("%d",anss[i][j]);
                }
                printf("
    ");
            }
        }
    }
    void dfs(int x,int y,int cnt)
    {
        int k = s[x][y];
        //cout << x << y << " " << s[x][y]<< endl;
        int xx,yy;
        for(int i = 0; i < 4; ++i)
        {
            xx = x + dx[i];
            yy = y + dy[i];
            if(k >= fc[i]) {
                k-=fc[i];
                continue;
            }
            if(kua[xx][yy] == 0){
                kua[xx][yy] = cnt;
                dfs(xx,yy,cnt);
            }
        }
        arr[x][y] = k;
    }
  • 相关阅读:
    Calling a parent window function from an iframe
    JSON with Java
    Posting array of JSON objects to MVC3 action method via jQuery ajax
    What's the difference between jquery.js and jquery.min.js?
    jquery loop on Json data using $.each
    jquery ui tabs详解(中文)
    DataTables warning requested unknown parameter
    Datatables 1.10.x在命名上与1.9.x
    jQuery 1.x and 2.x , which is better?
    DataTabless Add rows
  • 原文地址:https://www.cnblogs.com/mltang/p/9785836.html
Copyright © 2011-2022 走看看