HDU 4069 Squiggly Sudoku Dancing-Links(DLX)+Floodfill

题目大意:。。还是数独,不同的是原先的九宫格约束条件变为了给定的任意形状。。。

我们跑一遍floodfill 得出每一个格子属于哪一个形状

然后就是裸的数独了

这题T<=2500 绝对不能开动态 清则TLE 不清MLE 只能数组模拟

好不容易改完了 尼玛 交上去就WA

最后发现当找到一组解之后 一定要把当前的数独转移到ANS数组中 否则就会被覆盖 导致输出时错误

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct abcd{
    int l,r,u,d;
    int x,y,num;
    int bottom;
    void del();
    void restore();
}table[4000];
int head,tot,stack[4000],top;
int m,n,cnt,flag,map[9][9],belong[9][9],input[9][9],ans[9][9];
void del_column(int pos)
{
    int i,j;
    for(i=table[pos].u;i;i=table[i].u)
    {
        for(j=table[i].l;j;j=table[j].l)
            table[j].del();
        for(j=table[i].r;j;j=table[j].r)
            table[j].del();
        table[i].del();
    }
    table[pos].del();
}
inline void output()
{
    int i,j;
    for(i=0;i<9;i++)
    {
        for(j=0;j<9;j++)
            putchar(ans[i][j]+'0');
        putchar('\n');
    }
}
void DLX()
{
    if(!table[head].r)
    {
        memcpy(ans,map,sizeof ans);
        flag++;
        return ;
    }
    int i,mini,bottom=top,minnum=0x7fffffff;
    for(i=table[head].r;i;i=table[i].r)
        if(table[i].x<minnum)
            minnum=table[i].x,mini=i;
    for(i=table[mini].u;i;i=table[i].u)
    {
        int x=table[i].x,y=table[i].y,num=table[i].num;
        map[x][y]=num;

        del_column(x*9+y+2                      );
        del_column(81+x*9+num+1                  );
        del_column(162+y*9+num+1              );
        del_column(243+(belong[x][y])*9+num+1 );

        DLX();
        while(top!=bottom)
            table[stack[top--]].restore();
        if(flag>=2)
            return ;
    }
}
int New(int L,int R,int U,int D,int X,int Y,int Num)
{
    ++tot;
    table[tot].l=L;if(L)table[L].r=tot;
    table[tot].r=R;if(R)table[R].l=tot;
    table[tot].u=U;if(U)table[U].d=tot;
    table[tot].d=D;if(D)table[D].u=tot;
    table[tot].x=X;table[tot].y=Y;table[tot].num=Num;
    table[tot].bottom=D;
    if(table[tot].bottom)
        table[table[tot].bottom].x++;
    return tot;
}
void abcd :: del()
{
    if(l)table[l].r=r;
    if(r)table[r].l=l;
    if(u)table[u].d=d;
    if(d)table[d].u=u;
    if(bottom)
        table[bottom].x--;
    stack[++top]=this-table;
}
void abcd :: restore()
{
    if(l)table[l].r=this-table;
    if(r)table[r].l=this-table;
    if(u)table[u].d=this-table;
    if(d)table[d].u=this-table;
    if(bottom)
        table[bottom].x++;
}
void add(int x,int y,int num)
{
    int last=0,temp;
    temp=x*9+y+2                   ,last=New(last,0,table[temp].u,temp,x,y,num);
    temp=81+x*9+num+1               ,last=New(last,0,table[temp].u,temp,x,y,num);
    temp=162+y*9+num+1               ,last=New(last,0,table[temp].u,temp,x,y,num);
    temp=243+(belong[x][y])*9+num+1,last=New(last,0,table[temp].u,temp,x,y,num);
}
void initialize()
{
    int i;

    top=0;flag=0;cnt=0;tot=0;
    head=New(0,0,0,0,0,0,0);
    memset(map,-1,sizeof map);
    for(i=1;i<=81*4;i++)
        New(i,0,0,0,0,0,0);
}
void floodfill(int x,int y)
{
    if(~map[x][y])
        return ;
    belong[x][y]=cnt;
    map[x][y]=input[x][y]&15;
    if(~input[x][y]&16 )floodfill(x-1,y);
    if(~input[x][y]&32 )floodfill(x,y+1);
    if(~input[x][y]&64 )floodfill(x+1,y);
    if(~input[x][y]&128)floodfill(x,y-1);
}
int main()
{
    int T,i,j,k,x,Case=0;

    //freopen("sudoku.in","r",stdin);
    //freopen("sudoku.out","w",stdout);

    for(cin>>T;T;T--)
    {
        initialize();
        printf("Case %d:\n",++Case);

        for(i=0;i<9;i++)
            for(j=0;j<9;j++)
                scanf("%d",&input[i][j]);

        for(i=0;i<9;i++)
            for(j=0;j<9;j++)
                if(map[i][j]==-1)
                    floodfill(i,j),cnt++;

        for(i=0;i<9;i++)
            for(j=0;j<9;j++)
                if(map[i][j])
                    add(i,j,map[i][j]);
                else
                    for(k=1;k<=9;k++)
                        add(i,j,k);
        DLX();
        if(!flag)
            puts("No solution");
        else if(flag==1)
            output();
        else
            puts("Multiple Solutions");
    }
}
时间: 2024-10-28 22:46:51

HDU 4069 Squiggly Sudoku Dancing-Links(DLX)+Floodfill的相关文章

(中等) HDU 4069 Squiggly Sudoku , DLX+精确覆盖。

Description Today we play a squiggly sudoku, The objective is to fill a 9*9 grid with digits so that each column, each row, and each of the nine Connecting-sub-grids that compose the grid contains all of the digits from 1 to 9. Left figure is the puz

[DLX+bfs] hdu 4069 Squiggly Sudoku

题意: 给你9*9的矩阵.对于每个数字,能减16代表上面有墙,能减32代表下面有墙... 最后剩下的数字是0代表这个位置数要求,不是0代表这个数已知了. 然后通过墙会被数字分成9块. 然后做数独,这里的数独不是分成9个3*3的小块而是通过墙分成的. 思路: 首先通过数字作出墙. 然后bfs求连通块,dfs也可以.目的是分块. 然后就是dlx数独模板题了. 这里要注意的是如果找到答案2次就说明有多组解了,就应该停止返回了.不然会TLE. 代码: #include"stdio.h" #in

HDU 4069 Squiggly Sudoku【舞蹈链】【样例坑】

建模思路跟之前的一样,宫的话dfs搜索一下找联通分量就行,好像也没有更好的办法,有的话请评论哈orz --因为舞蹈链一般找到解以后就直接跳出了,所以ans数组就是ans不会再变.但这题让找一下有没有多组解,所以就不能找到一个解后直接跳出.就有一个小坑是都搜完后ans数组可能不是合法ans,所以找到第一个解的时候要单独存一下才能ac --但这个样例就是如果中间不存一下ans数组的话,样例还是能过... --那应该就是正好最后一次枚举的时候找到了这个解?? --不然的话它回溯的时候枚举下一个可能会覆

poj 3074 Sudoku(Dancing Links)

Sudoku Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8152   Accepted: 2862 Description In the game of Sudoku, you are given a large 9 × 9 grid divided into smaller 3 × 3 subgrids. For example, . 2 7 3 8 . . 1 . . 1 . . . 6 7 3 5 . . .

POJ 3076 Sudoku (dancing links)

题目大意: 16*16的数独. 思路分析: 多说无益. 想说的就是dancing links 的行是按照 第一行第一列填 1 第一行第二列填 2 -- 第一行第十五列填15 第一行第二列填 1 -- 第二行.... 列的纺织则是 第一行放1,第一行放2,..第十六行放16...第一列放1..第一列放2...第十六列放16..第一块区域放1 ....然后在最后81位就是放自己的位置,准确的说就是 r*m+c. #include <cstdio> #include <iostream>

Dancing Links [Kuangbin带你飞] 模版及题解

学习资料: http://www.cnblogs.com/grenet/p/3145800.html http://blog.csdn.net/mu399/article/details/7627862 2份模版 第一份精确覆盖 from POJ 3074 const int N = 9; const int MAXN = N * N * N + 10; const int MAXM = N * N * 4 + 10; const int MAXNODE = MAXN * 4 + MAXM +

POJ 2676 Sudoku (搜索,Dancing Links)

题目: http://poj.org/problem?id=2676 题意: 数独,每行1-9,每列1-9,每3*3小格1-9,填数,不能重复 方法:Dancing Links(16ms)或者DFS暴搜(400-900ms) Dancing Links(DLX) 是为了解决矩阵精确覆盖问题的算法,算法效率非常高 使用DLX解决的问题必须转化为矩阵精确覆盖问题: 1.DLX详解: http://wenku.baidu.com/view/d8f13dc45fbfc77da269b126.html 2

Dancing Links 小结 (因为之前丢了一次稿,未完待续)

Dancing Links (DLX)是Knuth为了解决精确覆盖问题而提出的算法,很多搜索问题可以转化位精确覆盖问题从而使用Dancing Links解决(效率会比DFS高很多,因为里面常常蕴涵着意想不到的剪枝) 信息学竞赛中的DLX的问题类似网络流,只需建图+贴版即可 参考文献: 1.DLX的原理:Knuth的论文: 原版:http://arxiv.org/abs/cs/0011047 翻译版:http://wenku.baidu.com/view/d8f13dc45fbfc77da269b

HDU 3335 Divisibility dancing links 重复覆盖

分析: dlx重复覆盖的巧用,重复覆盖的原理恰好符合本题的筛选方式,即选择一个数后,该数的倍数或约数可以保证在之后的搜索中不会被选择 于是修改一下启发函数,求解最大的重复覆盖即可. 其实不一定不被选择,只是选择以后,要么达不成目标,要不达到目标,也不如不选择更优 举下面的例子 3 2 3 6 答案一看就是 2 初始的dancing links的表示是这样的 2   3   6 2    1   0   1 3    0   1   1 6    1   1   1 然后肯定先选第一列进行删 删