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. EL表达式中的“+-x/”四种运算符和条件,比较运算符等

    <%@page import="cn.hncu.domain.User"%><%@ page language="java" import=& ...

  2. .Net设计模式_工厂模式(3)

    3.抽象工厂模式 引言: 我们知道汽车需要很多部件才能组装成一辆成品的车,那么我们需要汽车厂生产很多东西,如:马达.车轴.轮胎等,这些东西组装起来后成为了一辆车. 这些东西就是产品族,图解:(出之ht ...

  3. C语言实现电话本 动态开辟 信息存储于文件

    下面是我用C写的一个电话本小项目,实现的功能有:添加 删除 修改 查找 排序 清空 显示,功能还是比较全的,内存也是动态开辟的.能存储于本地,能从本地读出并显示 头文件部分代码,contact.h: ...

  4. gulp自动化框架的搭建

    自动化框架的搭建:https://github.com/zjhsd2007/www 屏蔽掉的部分是Test(文件夹的目录 也是你的项目名称);本地项目启动后 配合sass,会自动启动浏览器,然后好处多 ...

  5. mysql的having语句

    mysql> use qq; Database changed mysql> #查询本店价比市场价省的钱,并且要求省钱200元以上的取出来 mysql> select goods_i ...

  6. LSJ_NHibernate第四章 MVC

    前言: MVC现在已经成为web开发的一个主流趋势了,还没用过的小伙伴,你们已经落伍了,这里我推荐一篇学习博客 玩转Asp.net MVC 的八个扩展点  代码完全开源,下载地址:https://gi ...

  7. 【C#】获取本地Cookie的问题

    using System; using System.Net; using System.IO; using System.Text; // // TODO: 在此处添加代码以启动应用程序 // st ...

  8. WKWebView不显示提示框(Swift)

    使用WKWebView的时候会出现明明自己做的一些页面有提示框, 为什么使用别人的页面提示框总是不显示, 其实很大部分原因是因为该提示框是通过JS调用的, 需要实现WKUIDelegate来进行监听 ...

  9. Token 的作用

    Token,就是令牌,最大的特点就是随机性,不可预测.一般黑客或软件无法猜测出来. 那么,Token有什么作用?又是什么原理呢? Token一般用在两个地方: 1)防止表单重复提交. 2)anti c ...

  10. maven打war包注意之xml、properties文件没打进去解决方法

    maven项目在ide中编译出的war包一般不会有很多问题. 但是经过集成环境打war包会出现war包中打不进xml.properties等文件.这样打war包不会报错,但是war包放进tomcat中 ...