UVA Live 7957 (Gym 101201F) Illumination 2-SAT

https://icpcarchive.ecs.baylor.edu/external/79/7957.pdf

 

7957 Illumination
You inherited a haunted house. Its floor plan is an n × n square grid with l
lamps in fxed locations and no interior walls. Each lamp can either illuminate
its row or its column, but not both simultaneously. The illumination of each
lamp extends by r squares in both directions, so a lamp unobstructed by an
exterior wall of the house can illuminate as many as 2r + 1 squares.
If a square is illuminated by more than one lamp in its row, or by more
than one lamp in its column, the resulting bright spot will scare away ghosts
forever, diminishing the value of your property. Is it possible for all lamps to
illuminate a row or column, without scaring any ghosts? Note that a square
illuminated by two lamps, one in its row and the other in its column, will not
scare away the ghosts.
 

Input
The input fle contains several test cases, each of them as described below.
The frst line contains three positive integers, n, r and l (1 ≤ n; r; l ≤ 1; 000, l ≤ n2).
Each of the next l lines contains two positive integers ri and ci (1 ≤ ri; ci ≤ n), indicating that there
is a lamp in row ri and column ci.
It is guaranteed that all lamps are in distinct locations.


Output
For each test case, print, on a single line, ‘YES’ if it is possible to illuminate all lamps as stated above;
otherwise, print ‘NO’.
 

 

一个n*n的房子,有很多灯,每个格子只能被上下方向照一次、左右方向照一次,每个灯可以选择上下或是左右照,照明长度以自身位置为中心,占用2*r+1个格子。问能否安排一种方案,使所有格子满足条件。

 

经典2-SAT问题,把横照和竖照看做两个状态,对于格子A,一个是A,一个是A'.

因为每个格子可以同时在横向和竖向各照一次,所以行列都不同的灯之间其实并没有关系。

若某两个格子列相同,则其中一个为横向另一个必须是纵向,反之亦然。连边A->B',B->A'.

若某两个格子行相同,则其中一个为纵向另一个必须是横向,反之亦然。连边A'->B,B'->A.

建好图之后直接dfs就可以。

 

 

#include <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
const int maxn=1005,maxk=2000005,inf=0x3f3f3f3f;  
const ll llinf=0x3f3f3f3f3f3f3f3f;   
const ld pi=acos(-1.0L); 
int color[maxn*2],x[maxn],y[maxn],head[maxn*2],dfn[maxn*2];
int num;

struct Edge {
	int from,to,pre;
};
Edge edge[maxk];

void addedge(int from,int to) {
	edge[num]=(Edge){from,to,head[from]};
	head[from]=num++;
}

bool dfs(int now) {
	if (color[now]==1) return true;
	if (color[now]==2) return false;
	color[now]=1;
	color[now^1]=2;
	dfn[++num]=now;
	for (int i=head[now];i!=-1;i=edge[i].pre) {
		int to=edge[i].to;
		if (!dfs(to)) return false;
	}
	return true;
}

int main() {
	int n,r,l,i,j;
	num=0;
	memset(head,-1,sizeof(head));
	scanf("%d%d%d",&n,&r,&l);
	for (i=0;i<l;i++) {
		scanf("%d%d",&x[i],&y[i]);
		for (j=0;j<i;j++) {
			if (x[i]==x[j]) {
				if (abs(y[i]-y[j])<=2*r) addedge(j*2,(i*2)^1),addedge(i*2,(j*2)^1);
			} else if (y[i]==y[j]) {
				if (abs(x[i]-x[j])<=2*r) addedge((j*2)^1,i*2),addedge((i*2)^1,j*2);
			}
		}
	}
/*	for (i=0;i<num;i++) {
		if (edge[i].from%2==0) cout << edge[i].from/2+1; 
		    else cout << edge[i].from/2+1 << '*'; 
		cout << "  ";
		if (edge[i].to%2==0) cout << edge[i].to/2+1; 
		    else cout << edge[i].to/2+1 << '*'; 
		cout << "\n";
	}*/
	mem0(color);
	for (i=0;i<l;i++) {
			if (!color[i*2]) {
				num=0;
				if (!dfs(i*2)) {
					for (j=1;j<=num;j++) 
						color[dfn[j]]=color[dfn[j]^1]=0;
					if (!dfs(i*2+1)) {
				    	printf("NO");
				    	return 0;
			    	}
				}
			}
		}
	printf("YES");
	return 0;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值