Uva 1514 && spoj 9890 拆点匹配L模板 + 时间戳优化

本文介绍了一种解决特定L型拼图问题的算法实现,该算法通过将黑色方块分解为两个点来构建匹配图,并利用二分匹配的方法判断是否能够完全覆盖给定的黑白模式。

题目链接: http://www.spoj.com/problems/NWERC11D/

Piece it together

Tom has developed a special kind of puzzle: it involves a whole bunch of identical puzzle pieces. The pieces have the shape of three adjoint squares in an L-shape. The corner square is black, the two adjacent squares are white.

 


 

PIC

Figure 1: A puzzle piece

 


 

The puzzler is given a pattern of black and white squares in a rectangular grid. The challenge is to create that pattern using these pieces. The pieces can be rotated, but must not overlap.

Tom has already designed a few nice patterns, but he needs to find out if they can be constructed with the pieces at all. Rather than trying to test this for each pattern by hand, he wants to write a computer program to determine this for him. Can you help him?

Input

On the first line a positive integer: the number of test cases, at most 100. After that per test case:

  • one line with two integers and (1 ≤ n,m ≤ 500): the height and width of the grid containing the pattern, respectively.
  • lines, each containing characters, denoting the grid. Each character is ‘B’, ‘W’, or ‘.’, indicating a black, white or empty square respectively.

The grid contains at least one black or white square.

 

Output

Per test case:

  • one line with either “YES” or “NO”, indicating whether or not it is possible to construct the pattern with the puzzle pieces. You may assume that there is an infinite supply of pieces.

 

Sample in- and output

Input

Output

2
3 4
BWW.
WWBW
..WB
3 3
W..
BW.
WBW
YES
NO 

题意:

用L型模版匹配给定矩阵

(模版为左下角黑色,其他白色的2块)

问:

能否完美匹配矩阵

 

思路:

把黑块拆成2点, A点匹配上下的白色, A'匹配左右的白色

这里把二分匹配中 memset(T,0,sizeof(T)) ; 优化成 Time

 

#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <string.h>
#include <stdio.h>
#define ll int
#define N 500010
using namespace std;
inline ll Max(ll a, ll b){return a>b?a:b;}struct node{
	int to, nex;
}edge[N*2];
int head[N],edgenum ;
void addedge(int u, int v){
	node E = {v, head[u]};
	edge[ edgenum ] = E;
	head[u] = edgenum ++;
}int xn, T[N], lef[N], Time;
bool  IsB[N];int match(int x){
	for(int i = head[x]; i!=-1; i = edge[i].nex)
	{
		int v = edge[i].to;
		if(T[v] == Time)continue;
		T[v] = Time;
		if(lef[v] == -1 || match(lef[v]))
		{ 
			lef[v] = x;
			return 1;
		}
	}
	return 0; 
}int solve(){
	int ans = 0;
	memset(lef, -1, sizeof(lef));
	for(int i = 0; i <= xn; i++)
		if(IsB[i])
		{ Time++; ans += match( i ); }
		return ans ;
}int n, m;
int map[505][505],step[4][2] = {0,1,0,-1,1,0,-1,0};
char s[505];bool Inmap(int x,int y){ return (x>=0 && x<n && y>=0 && y<m)? true : false;}
void Have_map(){
	memset(head, -1, sizeof(head)),  edgenum = 0;
	memset(IsB, 0, sizeof(IsB));
	xn = -1;
	for(int i = 0; i < n; i++)
		for(int j = 0; j < m; j++)
			if(map[i][j] == 1)
				for(int k = 0; k < 4; k++)
				{
					int nowx = i+step[k][0], nowy = j + step[k][1];
					if(Inmap(nowx, nowy) && map[nowx][nowy]==2)
					{
						if(k==0 || k==1)
							addedge(i*m+j, nowx*m + nowy);
						else
							addedge(n*m + i*m+j, nowx*m + nowy);
						IsB[i*m+j] = IsB[n*m + i*m+j] = true;
						xn = n*m + i*m +j;
					}
				}
}
int main(){
	int t;scanf("%d",&t);
	Time = 1;
	memset(T, 0, sizeof(T)); while(t--){
		memset(map, 0, sizeof(map));
		scanf("%d %d",&n,&m);
		int B = 0, W = 0;
		for(int i = 0; i < n; i++)
		{
			scanf("%s",s);
			for(int j = 0; j < m; j++)
			{
				if(s[j] == 'B')
					B++, map[i][j] = 1;
				else if(s[j] == 'W')
					W++, map[i][j] = 2;
			}
		}
		if(W != B*2){ printf("NO\n");continue;}
		Have_map();
		printf("%s\n", (solve() == W)? "YES":"NO");
	}
	return 0;
}


 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值