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
",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("
");
        }
}
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
",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
",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);
        }
}
by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

本博客已停用,新博客地址:http://mhy12345.xyz

原文地址:https://www.cnblogs.com/mhy12345/p/4223107.html