题意:给一个$n\times m$的网格,对这个网格黑白染色,左上角为黑色。现在要用一些大小为$3$的L型图形覆盖这个网格,要求不能重复覆盖同一个格子,不能覆盖到障碍,L型可以进行旋转,但转角处格子必须为黑色,求最多能覆盖多少个L型图形

人生第一次上TC做题2333,最近机房网络不太稳定,lantern也经常崩,所以做这道题用了十几分钟才成功提交一次==

无论怎么旋转L型,两个白格必定不在同一行

所以$S$向奇数行白格连边,奇数行白格向相邻黑格连边,黑格向相邻偶数行白格连边,偶数行白格向$T$连边,这样跑最大流就对应着许多L型图形

为了保证每个格子最多被用一次,拆点连边限制流量即可

#include<stdio.h>
#include<string.h>
#include<vector>
#include<string>
using namespace std;
const int inf=2147483647;
int min(int a,int b){return a<b?a:b;}
int h[5010],cur[5010],nex[30010],to[30010],cap[30010],dis[5010],q[5010],M=1,S,T;
void add(int a,int b,int c){
	M++;
	to[M]=b;
	cap[M]=c;
	nex[M]=h[a];
	h[a]=M;
	M++;
	to[M]=a;
	cap[M]=0;
	nex[M]=h[b];
	h[b]=M;
}
bool bfs(){
	int head,tail,x,i;
	memset(dis,-1,sizeof(dis));
	head=tail=1;
	q[1]=S;
	dis[S]=0;
	while(head<=tail){
		x=q[head];
		head++;
		for(i=h[x];i;i=nex[i]){
			if(cap[i]&&dis[to[i]]==-1){
				dis[to[i]]=dis[x]+1;
				if(to[i]==T)return 1;
				tail++;
				q[tail]=to[i];
			}
		}
	}
	return 0;
}
int dfs(int x,int flow){
	if(x==T)return flow;
	int i,f;
	for(i=cur[x];i;i=nex[i]){
		if(cap[i]&&dis[to[i]]==dis[x]+1){
			f=dfs(to[i],min(flow,cap[i]));
			if(f){
				cap[i]-=f;
				cap[i^1]+=f;
				if(cap[i])cur[x]=i;
				return f;
			}
		}
	}
	dis[x]=-1;
	return 0;
}
int dicnic(){
	int ans=0,tmp;
	while(bfs()){
		memcpy(cur,h,sizeof(h));
		while(1){
			tmp=dfs(S,inf);
			if(tmp==0)break;
			ans+=tmp;
		}
	}
	return ans;
}
const int gx[4]={1,-1,0,0},gy[4]={0,0,1,-1};
char s[50][50];
int n,m;
int p(int x,int y){return(x-1)*m+y;}
int in(int x,int y){return p(x,y)*2-1;}
int ou(int x,int y){return p(x,y)<<1;}
int col(int x,int y){
	if(~(x+y)&1)return 2;
	return(~x&1)*2+1;
}
bool ok(int x,int y){return 0<x&&x<=n&&0<y&&y<=m&&s[x][y]=='.';}
class TheTilesDivOne{
	public:
		int find(vector<string>board){
			int i,j,k,x,y;
			n=board.size();
			m=board[0].length();
			for(i=1;i<=n;i++)strcpy(s[i]+1,board[i-1].c_str());
			S=n*m*2+1;
			T=n*m*2+2;
			for(i=1;i<=n;i++){
				for(j=1;j<=m;j++){
					if(s[i][j]=='.'){
						add(in(i,j),ou(i,j),1);
						if(col(i,j)==1)add(S,in(i,j),1);
						if(col(i,j)==3)
							add(ou(i,j),T,1);
						else{
							for(k=0;k<4;k++){
								x=i+gx[k];
								y=j+gy[k];
								if(ok(x,y)&&col(i,j)+1==col(x,y))add(ou(i,j),in(x,y),1);
							}
						}
					}
				}
			}
			return dicnic();
		}
};
/*
vector<string>v;
TheTilesDivOne test;
char str[50];
int main(){
	int n,m,i;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++){
		scanf("%s",str);
		v.push_back(str);
	}
	printf("%d",test.find(v));
}
*/

辣鸡TC连warning都不给过,差评==

[SRM570]TheTiles的更多相关文章

  1. Topcoder SRM570 900 CurvyonRails

    题意:给定一个网格,一些格子是障碍不用管,剩余的格子是城市,你可以修建铁路,铁路的形状可以是直的或者弯的,也就是说可以以这个点为节点连接它四联通的其中两个方块.要求用一个或多个环来覆盖所有城市.对于有 ...

  2. Topcoder SRM570 D1L3 CurvyonRails

    几个样例: 5 5wCCwwwCC....w......www..wReturns: 0 3 3C.w....C.Returns: 1 21 20CC..CCCw.CwC..CC.w.CC.CCCwC ...

随机推荐

  1. 如何用PhotoShop制作网站的favicon.ico

    所谓favicon,即Favorites Icon的缩写,顾名思义,便是其可以让浏览器的收藏夹中除显示相应的标题外,还以图标的方式区别不同的网站.当然,这不仅仅是Favicon的全部,根据浏览器的不同 ...

  2. bzoj 1124 [POI2008]枪战Maf 贪心

    [POI2008]枪战Maf Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 741  Solved: 295[Submit][Status][Disc ...

  3. MAC地址的介绍(单播、广播、组播、数据收发)

    MAC地址组成 网络设备的MAC地址是全球唯一的.MAC地址长度为48比特,通常用十六进制表示.MAC地址包含两部分:前24比特是组织唯一标识符(OUI,OrganizationallyUniqueI ...

  4. Every Programmer Should Know These Latency Numbers

    Every Programmer Should Know These Latency Numbers 1秒=1000毫秒(ms) 1秒=1,000,000 微秒(μs) 1秒=1,000,000,00 ...

  5. 我自己的python开发环境

    1.开发工具 eclipse 所有的版本下载: https://www.eclipse.org/downloads/index-packages.php , 我下载的是比较低的版本:https://w ...

  6. 转:Nginx国人开发缩略图模块(ngx_image_thumb)

    ngx_image_thumb是nginx中用来生成缩略图的模块,生存缩略图的方法很多,之前也写过一篇 <nginx生成缩略图配置>,在github上发现国人开发的一款模块,作者的文档写的 ...

  7. shell正则表达式(1)

    一.什么是正则 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则. 二.grep 1.参数 -n  :显示行号 -o  : ...

  8. 【POJ 1719】 Shooting Contest (二分图匹配)

    题目链接 把每一列能射的两行和这一列连边,然后跑一边匈牙利就行了. #include <cstdio> #include <cstring> #include <algo ...

  9. 【洛谷 P3629】 [APIO2010]巡逻 (树的直径)

    题目链接 容易发现,当加一条边时,树上会形成一个环,这个环上的每个点都是只要走一次的,也就是说我们的答案减少了这个环上点的个数,要使答案最小,即要使环上的点最多,求出直径\(L\),则答案为\(2(n ...

  10. JHDU 2601 An easy problem (数学 )

    title: An easy problem 数学 杭电2601 tags: [数学] 题目链接 Problem Description When Teddy was a child , he was ...