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=;
const int maxv=;
const int maxn=;
const int mov[][]={{,},{-,},{,-},{,}};
struct Edge
{
int np,val;
Edge *next;
}E[maxe],*V[maxv];
int tope=-;
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=;i<t;i++)
{
scanf("%d%d",&x,&y);
bad[x][y]=true;
}
for (i=;i<=n;i++)
{
for (j=;j<=m;j++)
{
if (bad[i][j] || ((i+j)&))continue;
for (k=;k<;k++)
{
if (i+mov[k][]> && i+mov[k][]<=n
&& j+mov[k][]> && j+mov[k][]<=m
&& !bad[i+mov[k][]][j+mov[k][]])
{
addedge(i*m+j,(i+mov[k][])*m+j+mov[k][]);
}
}
}
}
int ans=;
for (i=;i<=n;i++)
{
for (j=;j<=m;j++)
{
if ((i+j)%==)
{
memset(vis,,sizeof(vis));
ans+=find(i*m+j);
}
}
}
printf("%d\n",ans);
return ;
}
}
namespace sec2
{
const int maxn=;
int a[maxn];
long long b[maxn];
void main(const char* str)
{
int m=strlen(str);
for (int i=;i<m;i++)
a[(m-i-)/]=a[(m-i-)/]*+str[i]-'';
int n=(m-)/;
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
{
b[i+j]+=(long long)a[i]*a[j];
b[i+j+]+=b[i+j]/;
b[i+j]%=;
}
for (int i=;i<n*+;i++)
{
b[i+]+=b[i]/;
b[i]%=;
}
n=n*+;
while (!b[n])n--;
b[]--;
for (int i=n;i>=;i--)
{
b[i-]+=b[i]%*;
b[i]/=;
}
while (!b[n])n--;
printf("%lld",b[n]);
for (int i=n-;i>=;i--)
printf("%08lld",b[i]);
printf("\n");
}
}
namespace sec3//DLX
{
//{{{
const int maxn=;
const int maxd=maxn*maxn**;
const int mov[][]={{,},{-,},{,-},{,}};
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[];
int ans=,cnt=;
int topd=;
int anslim;
void Init_DLX(int l)
{
int now;
L[]=R[]=D[]=U[]=;
for (int i=;i<=l;i++)
{
now=++topd;
R[now]=head[];
L[now]=L[head[]];
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[];
U[now]=U[head[]];
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[]];
for (int i=R[head[]];i!=head[];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+);
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[]=-;
int x,y;
for (i=;i<t;i++)
{
scanf("%d%d",&x,&y);
bad[x][y]=true;
}
anslim=(n*m-t)/;
Init_DLX((n+)*m);
for (i=;i<=n;i++)
{
for (j=;j<=m;j++)
{
if (bad[i][j])continue;
for (k1=;k1<;k1++)
{
if (i+mov[k1][]== || i+mov[k1][]==n+
|| j+mov[k1][]== || j+mov[k1][]==m+
|| bad[i+mov[k1][]][j+mov[k1][]])
continue;
for (k2=k1+;k2<;k2++)
{
if (i+mov[k2][]== || i+mov[k2][]==n+
|| j+mov[k2][]== || j+mov[k2][]==m+
|| bad[i+mov[k2][]][j+mov[k2][]])
continue;
vec[]=i*m+j;
vec[]=(i+mov[k2][])*m+j+mov[k2][];
vec[]=(i+mov[k1][])*m+j+mov[k1][];
Add_DLX(vec);
}
}
}
}
Search_DLX();
printf("%d\n",ans);
}
//}}}
}
char str[];
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);
}
}

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

  1. BZOJ2706 : [SDOI2012]棋盘覆盖

    A类数据: 将棋盘黑白染色,相邻的点之间连边,求出二分图最大匹配即可. B类数据: 答案为$\lfloor\frac{n^2-1}{3}\rfloor$,用FFT加速计算即可,时间复杂度$O(L\lo ...

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

    利用 Dancing Link 来解数独 详细的能够看    lrj 的训练指南 和 < Dancing Links 在搜索中的应用 >这篇论文 Dancing Link 来求解数独 , ...

  3. dancing link模板

    #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #i ...

  4. dancing link 学习资源导航+心得

    dancing link简直是求解数独的神器,NOIP2009最后一题靶形数独,DFS 各种改变搜索顺序 都没法过,最后还是用了卡时过得.用dancing link写,秒杀所有数据,总时间才400ms ...

  5. 【Dancing Link专题】解题报告

    DLX用于优化精确覆盖问题,由于普通的DFS暴力搜索会超时,DLX是一个很强有力的优化手段,其实DLX的原理很简单,就是利用十字链表的快速删除和恢复特点,在DFS时删除一些行和列以减小查找规模,使得搜 ...

  6. 「CH6801」棋盘覆盖

    「CH6801」棋盘覆盖 传送门 考虑将棋盘黑白染色,两个都无障碍的相邻的点之间连边,边的容量都为1,然后就求一次最大匹配即可 参考代码: #include <cstring> #incl ...

  7. Dancing Link 详解(转载)

    Dancing Link详解: http://www.cnblogs.com/grenet/p/3145800.html Dancing Link求解数独: http://www.cnblogs.co ...

  8. hustoj 1017 - Exact cover dancing link

    1017 - Exact cover Time Limit: 15s Memory Limit: 128MB Special Judge Submissions: 5851 Solved: 3092 ...

  9. NYOJ 45 棋盘覆盖

    棋盘覆盖 水题,题不难,找公式难 import java.math.BigInteger; import java.util.Scanner; public class Main { public s ...

随机推荐

  1. linux安装java环境

    在linux下安装JDK如下: 第一步:查看Linux自带的JDK是否已安装 (1)查看已经安装的jdk: [root@web-server ~]# rpm -qa|grep jdk ← 查看jdk的 ...

  2. 图灵API

    namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine( ...

  3. 20160418javaweb之 Filter过滤器

    Servlet规范中 Servlet Listener Filter 1.开发Filter 想要开发一个过滤器需要如下两个步骤: (1)写一个类实现特定的接口Filter 生命周期:当服务器启动时,w ...

  4. PHP和MYSQL的编码问题

    http://blog.csdn.net/martinkro/article/details/5352474 1 MYSQL中的字符集概念  Mysql的字符集里有两个概念,一个是"Char ...

  5. Ext.Net学习笔记06:Ext.Net DirectEvents用方补充

    在ASP.NET控件上面使用DirectEvents 我们在ASP.NET中实现无刷新的页面请求的时候,通常会用到UpdatePanel,现在Ext.Net为我们提供了另外一种渠道:通过DirectE ...

  6. C#查询当前微信自定义菜单结构

    查询 string access_token = "你的token"; string posturl = "https://api.weixin.qq.com/cgi-b ...

  7. sqlite3 语句总结

      一. iOS客户端设计数据库时一般使用  sqlite,以sqlite3 为例,简单介绍一下. 二. sqlite3常用命令当前目录下建立或打开test.db数据库文件,并进入sqlite命令终端 ...

  8. OC与Swift的区别二(常量、变量、运算符)

    4.常量与变量声明 oc的变量声明使用  类型 变量名 = 变量值的方式,其中类型为系统内置数据类型或自定义类型,变量名需由英文字母开头且不能包含特殊字符 swift变量声明使用 var 变量名 = ...

  9. Unity中使用RequireComponent,没有添加上组件

    using UnityEngine; using System.Collections; [RequireComponent(typeof(MeshFilter), typeof(MeshRender ...

  10. 如何在Angular2中使用Forms

    在Angular2中形成两个基本对象是Control和ControlGroup. 控制用户输入 Control 一个控制表示一个输入字段(ngFormControl) 一个控制可以绑定到一个input ...