bzoj 2706: [SDOI2012]棋盘覆盖 Dancing Link
2706: [SDOI2012]棋盘覆盖
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 255 Solved: 77
[Submit][Status]
Description
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的更多相关文章
- BZOJ2706 : [SDOI2012]棋盘覆盖
A类数据: 将棋盘黑白染色,相邻的点之间连边,求出二分图最大匹配即可. B类数据: 答案为$\lfloor\frac{n^2-1}{3}\rfloor$,用FFT加速计算即可,时间复杂度$O(L\lo ...
- hdu 1426 Sudoku Killer ( Dancing Link 精确覆盖 )
利用 Dancing Link 来解数独 详细的能够看 lrj 的训练指南 和 < Dancing Links 在搜索中的应用 >这篇论文 Dancing Link 来求解数独 , ...
- dancing link模板
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #i ...
- dancing link 学习资源导航+心得
dancing link简直是求解数独的神器,NOIP2009最后一题靶形数独,DFS 各种改变搜索顺序 都没法过,最后还是用了卡时过得.用dancing link写,秒杀所有数据,总时间才400ms ...
- 【Dancing Link专题】解题报告
DLX用于优化精确覆盖问题,由于普通的DFS暴力搜索会超时,DLX是一个很强有力的优化手段,其实DLX的原理很简单,就是利用十字链表的快速删除和恢复特点,在DFS时删除一些行和列以减小查找规模,使得搜 ...
- 「CH6801」棋盘覆盖
「CH6801」棋盘覆盖 传送门 考虑将棋盘黑白染色,两个都无障碍的相邻的点之间连边,边的容量都为1,然后就求一次最大匹配即可 参考代码: #include <cstring> #incl ...
- Dancing Link 详解(转载)
Dancing Link详解: http://www.cnblogs.com/grenet/p/3145800.html Dancing Link求解数独: http://www.cnblogs.co ...
- hustoj 1017 - Exact cover dancing link
1017 - Exact cover Time Limit: 15s Memory Limit: 128MB Special Judge Submissions: 5851 Solved: 3092 ...
- NYOJ 45 棋盘覆盖
棋盘覆盖 水题,题不难,找公式难 import java.math.BigInteger; import java.util.Scanner; public class Main { public s ...
随机推荐
- Cookie中用户登录信息登录验证
public class FormServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpSer ...
- Activity 与ListActivity的区别
转载自 http://www.cnblogs.com/bravestarrhu/archive/2012/05/06/2486703.html
- CountDownLatch(倒计时计数器)使用说明
方法说明: public void countDown() 递减锁存器的计数,如果计数到达零,则释放所有等待的线程.如果当前计数大于零,则将计数减少.如果新的计数为零,出于线程调度目的, ...
- js 如何判断数据是数据还是对象
如果用typeof测试,数组和对象都是显示的Object, 测试方式:var mycars=new Array();mycars[0]="Saab";mycars[1]=" ...
- <input> 标签
HTML5 中的新属性. 属性 值 描述 accept mime_type 规定通过文件上传来提交的文件的类型. align left right top middle bottom 不赞成使用. ...
- 定时执行Timer
JAVA import java.awt.event.*; import java.io.BufferedWriter;import java.io.File;import java.io.FileO ...
- 深入分析 Java 中的中文编码问题 (文章来自网络)
许令波,developerWorks 中国网站最佳作者,现就职于淘宝网,是一名 Java 开发工程师.对大型互联网架构设计颇感兴趣,喜欢钻研开源框架的设计原理.有时间将学到的知识整理成文章,也喜欢记录 ...
- Web开发必备资源汇总[转]
导读:原文来自< Best “must know” open sources to build the new Web>,译文由酷壳网陈皓整理编译< 开源中最好的Web开发的资源 & ...
- LA 3902 Network(树上最优化 贪心)
Network Consider a tree network with n <tex2html_verbatim_mark>nodes where the internal nodes ...
- 暑假集训(1)第五弹 -----Rails(Uva514)
PopPush城市有一座著名的火车站.这个国家到处都是丘陵.而这个火车站是建于上一个世纪.不幸的是,那时的资金有限.所以只能建立起一条路面铁轨.而且,这导致这个火车站在同一个时刻只能一个轨道投入使用, ...