bzoj 2706: [SDOI2012]棋盘覆盖 Dancing Link

2706: [SDOI2012]棋盘覆盖

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 255  Solved: 77
[Submit][Status]

Description

在一个N*M个方格组成的棋盘内,有K个方格被称为特殊方格。我们要使用一组俄罗斯方块来覆盖这个棋盘,保证特殊方格不能被覆盖,非特殊方格只能被一个俄罗斯方块覆盖,求最多能容纳的俄罗斯方块的数量。

已知有以下三组俄罗斯方块,一个棋盘可能用其中的某一组。

Input

第一行三个整数,N,M,K,和一个字符,type,为所用的俄罗斯方块组。

接下来K行每行两个整数,X,Y,表示第X行第Y列为特殊方格。

Output

一个整数,为所求的答案。

【样例输入1】

8 8 0 A

【样例输出1】

32

【样例输入2】

7 6 6 C

3 1

3 6

5 3

5 4

5 7

6 7

【样例输出2】

12

【数据范围】


测试点


N,M


K


type


[1, 6]


0 < N,M <= 100


0<=K<=N*M


A


[7, 12]


N=M=2^L,0<L<=200000


K=1


B


[13, 20]


0<N,M<=11


0<=K<=N*M


C

  第一组:二分图匹配

  第二组:可以通过分治法证明ans=(n*n-1)/3

  第三组:我用的是Dancing Link,但是不知道有没有网络流解法,如果用dancing link那么要注意如果当前答案等于(n*m-k)/3就强制退出。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
namespace sec1
{
        const int maxe=21000;
        const int maxv=11000;
        const int maxn=102;
        const int mov[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
        struct Edge
        {
                int np,val;
                Edge *next;
        }E[maxe],*V[maxv];
        int tope=-1;
        bool bad[maxn][maxn];
        void addedge(int x,int y)
        {
                E[++tope].np=y;
                E[tope].next=V[x];
                V[x]=&E[tope];
        }
        bool vis[maxn*maxn];
        int ptr[maxn*maxn];
        bool find(int now)
        {
                Edge *ne;
                for (ne=V[now];ne;ne=ne->next)
                {
                        if (vis[ne->np])continue;
                        vis[ne->np]=true;
                        if (!ptr[ne->np] || find(ptr[ne->np]))
                        {
                                ptr[ne->np]=now;
                                return true;
                        }
                }
                return false;
        }
        int main(int n,int m,int t)
        {
                int i,j,k,x,y;
                for (i=0;i<t;i++)
                {
                        scanf("%d%d",&x,&y);
                        bad[x][y]=true;
                }
                for (i=1;i<=n;i++)
                {
                        for (j=1;j<=m;j++)
                        {
                                if (bad[i][j] || ((i+j)&1))continue;
                                for (k=0;k<4;k++)
                                {
                                        if (i+mov[k][0]>0 && i+mov[k][0]<=n
                                                        && j+mov[k][1]>0 && j+mov[k][1]<=m
                                                        && !bad[i+mov[k][0]][j+mov[k][1]])
                                        {
                                                addedge(i*m+j,(i+mov[k][0])*m+j+mov[k][1]);
                                        }
                                }
                        }
                }
                int ans=0;
                for (i=1;i<=n;i++)
                {
                        for (j=1;j<=m;j++)
                        {
                                if ((i+j)%2==0)
                                {
                                        memset(vis,0,sizeof(vis));
                                        ans+=find(i*m+j);
                                }
                        }
                }
                printf("%d\n",ans);
                return 0;
        }
}
namespace sec2
{
        const int maxn=1100000;
        int a[maxn];
        long long b[maxn];
        void main(const char* str)
        {
                int m=strlen(str);
                for (int i=0;i<m;i++)
                        a[(m-i-1)/8]=a[(m-i-1)/8]*10+str[i]-‘0‘;
                int n=(m-1)/8;
                for (int i=0;i<=n;i++)
                        for (int j=0;j<=n;j++)
                        {
                                b[i+j]+=(long long)a[i]*a[j];
                                b[i+j+1]+=b[i+j]/100000000;
                                b[i+j]%=100000000;
                        }
                for (int i=0;i<n*2+10;i++)
                {
                        b[i+1]+=b[i]/100000000;
                        b[i]%=100000000;
                }
                n=n*2+10;
                while (!b[n])n--;
                b[0]--;
                for (int i=n;i>=0;i--)
                {
                        b[i-1]+=b[i]%3*100000000;
                        b[i]/=3;
                }
                while (!b[n])n--;
                printf("%lld",b[n]);
                for (int i=n-1;i>=0;i--)
                        printf("%08lld",b[i]);
                printf("\n");
        }
}
namespace sec3//DLX
{
        //{{{
        const int maxn=12;
        const int maxd=maxn*maxn*4*4;
        const int mov[4][2]={{1,0},{-1,0},{0,-1},{0,1}};
        const int inf=0x3f3f3f3f;
        int L[maxd],R[maxd],D[maxd],U[maxd];
        bool bad[maxn][maxn];
        int tt[maxd];
        int top[maxd];
        int head[maxn*maxn];
        int vec[4];
        int ans=0,cnt=0;
        int topd=0;
        int anslim;
        void Init_DLX(int l)
        {
                int now;
                L[0]=R[0]=D[0]=U[0]=0;
                for (int i=1;i<=l;i++)
                {
                        now=++topd;
                        R[now]=head[0];
                        L[now]=L[head[0]];
                        U[now]=D[now]=now;
                        L[R[now]]=now;
                        R[L[now]]=now;
                        top[now]=i;
                        head[i]=now;
                }
        }
        void Add_DLX(int *ss)
        {
                int now=++topd;
                D[now]=head[0];
                U[now]=U[head[0]];
                L[now]=R[now]=now;
                D[U[now]]=now;
                U[D[now]]=now;
                int h0=now;
                while (~(*ss))
                {
                        now=++topd;
                        D[now]=head[*ss];
                        U[now]=U[head[*ss]];
                        L[now]=L[h0];
                        R[now]=h0;
                        U[D[now]]=now;
                        D[U[now]]=now;
                        R[L[now]]=now;
                        L[R[now]]=now;
                        top[now]=*ss;
                        tt[*ss]++;
                        ss++;
                }
        }
        void Cover(int c)
        {
                R[L[c]]=R[c];
                L[R[c]]=L[c];
                for (int i=D[c];i!=c;i=D[i])
                {
                        for (int j=R[i];j!=i;j=R[j])
                        {
                                tt[top[j]]--;
                                U[D[j]]=U[j];
                                D[U[j]]=D[j];
                        }
                }
        }
        void Resume(int c)
        {
                R[L[c]]=c;
                L[R[c]]=c;
                for (int i=D[c];i!=c;i=D[i])
                {
                        for (int j=R[i];j!=i;j=R[j])
                        {
                                tt[top[j]]++;
                                U[D[j]]=D[U[j]]=j;
                        }
                }
        }
        void Search_DLX(int tot)
        {
                ans=max(ans,tot);
                if (ans==anslim)return;
                int bst=inf,bstid;
                bstid=R[head[0]];
                for (int i=R[head[0]];i!=head[0];i=R[i])
                        if (tt[top[i]] && tt[top[i]]<bst)
                                bst=tt[top[i]],bstid=top[i];
                for (int i=D[head[bstid]];i!=head[bstid];i=D[i])
                {
                        int k;
                        for (k=R[i];top[k];k=R[k]);
                        for (int j=R[k];j!=k;j=R[j])Cover(head[top[j]]);
                        Search_DLX(tot+1);
                        for (int j=R[k];j!=k;j=R[j])Resume(head[top[j]]);
                }
        }
        void main(int n,int m,int t)
        {
                int i,j,k1,k2;
                vec[3]=-1;
                int x,y;
                for (i=0;i<t;i++)
                {
                        scanf("%d%d",&x,&y);
                        bad[x][y]=true;
                }
                anslim=(n*m-t)/3;
                Init_DLX((n+1)*m);
                for (i=1;i<=n;i++)
                {
                        for (j=1;j<=m;j++)
                        {
                                if (bad[i][j])continue;
                                for (k1=0;k1<4;k1++)
                                {
                                        if (i+mov[k1][0]==0 || i+mov[k1][0]==n+1
                                                        || j+mov[k1][1]==0 || j+mov[k1][1]==m+1
                                                        || bad[i+mov[k1][0]][j+mov[k1][1]])
                                                continue;
                                        for (k2=k1+1;k2<4;k2++)
                                        {
                                                if (i+mov[k2][0]==0 || i+mov[k2][0]==n+1
                                                                || j+mov[k2][1]==0 || j+mov[k2][1]==m+1
                                                                || bad[i+mov[k2][0]][j+mov[k2][1]])
                                                        continue;
                                                vec[0]=i*m+j;
                                                vec[1]=(i+mov[k2][0])*m+j+mov[k2][1];
                                                vec[2]=(i+mov[k1][0])*m+j+mov[k1][1];
                                                Add_DLX(vec);
                                        }
                                }
                        }
                }
                Search_DLX(0);
                printf("%d\n",ans);
        }
        //}}}
}
char str[110000];
int main()
{
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        int n,m,t;
        char type;
        scanf("%s %d %d %c\n",str,&m,&t,&type);
        if (type==‘A‘)
        {
                sscanf(str,"%d",&n);
                sec1::main(n,m,t);
        }else if (type==‘B‘)
        {
                sec2::main(str);
        }else if (type==‘C‘)
        {
                sscanf(str,"%d",&n);
                sec3::main(n,m,t);
        }
}
时间: 2024-08-29 07:05:21

bzoj 2706: [SDOI2012]棋盘覆盖 Dancing Link的相关文章

使用改良版多值覆盖Dancing link X (舞蹈链)求解aquarium游戏

在上一篇文章中,我们通过改造了dancing link代码解出了aquarium游戏,并输出了正确答案. 但是之前的代码感觉有些慢,10*10的谜面都要跑24秒,而且感觉之前的dancing link代码有些不完善(存在重复查询问题).这一篇文章介绍如何改良多值覆盖dancing link模板代码,还有如何在整体上优化这个游戏的解题流程. 之前的代码是从所有列中选择可能性最少的列进行突破,以减少查询宽度:但是在查询过程中发现了问题:之前查询过的较高占据值的行可能会再次被查询到,从而浪费不少时间.

BZOJ2706 : [SDOI2012]棋盘覆盖

A类数据: 将棋盘黑白染色,相邻的点之间连边,求出二分图最大匹配即可. B类数据: 答案为$\lfloor\frac{n^2-1}{3}\rfloor$,用FFT加速计算即可,时间复杂度$O(L\log L)$. C类数据: 轮廓线DP,对于轮廓线上每个格子,要么为空,要么被占据,要么被占据且还要向下延伸一格. 设$f[i][j][S][k]$表示考虑到$(i,j)$,轮廓线上$m$个格子状态为$S$,转角处被占据状态为$k$时最多能放几个俄罗斯方块. 时间复杂度$O(nm3^m)$. #inc

hdu 1426 Sudoku Killer ( Dancing Link 精确覆盖 )

利用 Dancing Link 来解数独 具体的可以看    lrj 的训练指南 和 < Dancing Links 在搜索中的应用 >这篇论文 Dancing Link 来求解数独 , 是通过求解精确覆盖 精确覆盖就是给出一个 01 矩阵 , 要求我们选择一些行 , 使得每一列有且仅有一个 1 对于数独问题 , 行就是我们的选择 , 即在第 i 行 第 j 列 放上 数字 k , 所以我们最多有 i * j * k 中选择 如果某些位置( x , y  )已经放了数字 a , 那么我们的选择

dancing link模板

1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<iomanip> 7 using namespace std; 8 9 const int n=729,m=324; 10 bool mx[2000][2000];//数独转化过来的01矩阵 11 int map[1

dancing link 学习资源导航+心得

dancing link简直是求解数独的神器,NOIP2009最后一题靶形数独,DFS 各种改变搜索顺序 都没法过,最后还是用了卡时过得.用dancing link写,秒杀所有数据,总时间才400ms不到..(虽然还不是很清楚为什么会快). 一开始还是先看这个blog,图文都非常清晰 http://www.cnblogs.com/grenet/p/3145800.html 上文解释了dancing link的原理,可以用来解决精度覆盖问题,但是求解数独问题还需要一步转化. 见博文: http:/

棋盘覆盖问题

棋盘覆盖问题       问题描述: 在一个2^k×2^k个方格组成的棋盘中,若有一个方格与其他方格不同,则称该方格为一特殊方格,且称该棋盘为一个特殊棋盘.显然特殊方格在棋盘上出现的位置有4^k种情形.因而对任何k≥0,有4^k种不同的特殊棋盘.     下图–图(1)中的特殊棋盘是当k=3时16个特殊棋盘中的一个: 图(1) 题目要求在棋盘覆盖问题中,要用下图-图(2)所示的4种不同形态的L型骨牌覆盖一个给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖. 图(2) 题目

计算机算法设计与分析之棋盘覆盖问题

一.引子 最近又重新上了算法课,现在想来有点汗颜,大学期间已经学习了一个学期,到现在却依然感觉只是把老师讲过的题目弄懂了,并没有学到算法的一些好的分析方法和思路,碰到一个新的问题后往往感觉很棘手,痛定思痛之后觉得还是好好再学习一遍,争取能理解透彻每种算法的思路和核心,同时也劝诫各位同行们做事要脚踏实地,不能应付老师的作业,最后吃亏的还是自己啊. 二.棋盘覆盖问题 在一个由2^k *2^k个方格组成的棋盘中,恰有一个方格与其他方格不同,称该方格为一特殊方格,且称该棋盘 为一特殊棋盘.现有四种L型骨

nyoj 45 棋盘覆盖

棋盘覆盖 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 在一个2k×2k(1<=k<=100)的棋盘中恰有一方格被覆盖,如图1(k=2时),现用一缺角的2×2方格(图2为其中缺右下角的一个),去覆盖2k×2k未被覆盖过的方格,求需要类似图2方格总的个数s.如k=1时,s=1;k=2时,s=5 输入 第一行m表示有m组测试数据: 每一组测试数据的第一行有一个整数数k; 输出 输出所需个数s; 样例输入 3 1 2 3 样例输出 1 5 21 /* 注意寻找图中规律

棋盘覆盖(大数阶乘,大数相除)

棋盘覆盖 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 在一个2k×2k(1<=k<=100)的棋盘中恰有一方格被覆盖,如图1(k=2时),现用一缺角的2×2方格(图2为其中缺右下角的一个),去覆盖2k×2k未被覆盖过的方格,求需要类似图2方格总的个数s.如k=1时,s=1;k=2时,s=5 图1 图2 输入 第一行m表示有m组测试数据:每一组测试数据的第一行有一个整数数k; 输出 输出所需个数s; 样例输入 3 1 2 3 样例输出 1 5 21 accept