codeforces#292-D. Drazil and Tiles-暴力/拓扑排序

http://codeforces.com/contest/515/problem/D

题意:

题目意思:输入一个n*m包括'*'和'.'的矩阵,'.'表示该位置为空。'*'表示该位置已有东西。用一个1*2的瓷砖去填满空位置,如果只有一种方法,输出该方法。如果无解或有2种以上的方法输出Not unique.

思路:题目简化成只要求我们求  存在且填法唯一的答案。

那么我们就从这个唯一入手,  如果一个空节点(也就是点)的度数为一(也就是周围只有1个空节点),那么我们就先填他,因为他的填法是唯一的,

并且填了它之后,我们要更新它隔壁的那一个刚被填掉的瓷砖的周围的点的度数,如果发现有度数为1的点,则push进队列


*******当队列为空之后,就是把所有 能够确定的唯一填法的瓷砖都填完了  接下来把图扫描一遍即可,如果还有空瓷砖,表示不能填满 或者 有多种方式填,  否则就是合法唯一答案



#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;

	int n,m;
struct node
{
	int x,y;
	node(){}
	node(int a,int b)
	{
		x=a;y=b;
	}
};
char tm[2005][2005];
queue <node> q;

int cal(int i,int j)
{
	int cun=0;
	if (i-1>=1 &&tm[i-1][j]=='.')
		cun++;
	if (i+1<=n &&tm[i+1][j]=='.')
		cun++;
	if (j-1>=1 &&tm[i][j-1]=='.')
		cun++;
	if (j+1<=m &&tm[i][j+1]=='.')
		cun++;
	return cun; 
	
}
int c_dir(node t)
{
	int i=t.x;
	int j=t.y;
	if (j-1>=1 &&tm[i][j-1]=='.')
		return 1;
	if (i-1>=1 &&tm[i-1][j]=='.')
		return 2;
	if (j+1<=m &&tm[i][j+1]=='.')
		return 3;
	if (i+1<=n && tm[i+1][j]=='.')
		return 4;
	
	return 0;  //注意不要漏掉
	
}
void change(node t)
{
	int i=t.x;
	int j=t.y;
	if (i-1>=1 &&cal(i-1,j)==2&&tm[i-1][j]=='.')
		q.push(node(i-1,j));
	if (i+1<=n &&cal(i+1,j)==2&&tm[i+1][j]=='.')
		q.push(node(i+1,j));
	if (j-1>=1 &&cal(i,j-1)==2&&tm[i][j-1]=='.')
		q.push(node(i,j-1));
	if (j+1<=m &&cal(i,j+1)==2&&tm[i][j+1]=='.')
		q.push(node(i,j+1)); 
	
}
int main()
{
	int i ,j;
	scanf("%d%d",&n,&m);
	getchar();
	for (i=1;i<=n;i++)
	{
		for (j=1;j<=m;j++)
		{
			scanf("%c",&tm[i][j]);
		}
		getchar();
	}
	
	for (i=1;i<=n;i++)
	{
		for (j=1;j<=m;j++)
		{
			if (tm[i][j]=='*') continue;
			if (cal(i,j)==1)
				q.push(node(i,j)); 
		}
	}
//	printf("size:%d\n",q.size());
	while(!q.empty())
	{
		node t=q.front();
		q.pop();
		int dir=0;
		dir=c_dir(t);
		if (dir==1)
		{
			
			change(node(t.x,t.y-1));
			tm[t.x][t.y]='>';
			tm[t.x][t.y-1]='<';
		}
		if (dir==2)
		{
			
			change(node(t.x-1,t.y));
			tm[t.x][t.y]='v';
			tm[t.x-1][t.y]='^';
		}
		if (dir==3)
		{
			
			change(node(t.x,t.y+1));
			tm[t.x][t.y]='<';
			tm[t.x][t.y+1]='>';
		}
		if (dir==4)
		{
			
			change(node(t.x+1,t.y));
			tm[t.x][t.y]='^';
			tm[t.x+1][t.y]='v';
		}
	}
	
	int flag=0;
	for (i=1;i<=n;i++)
	{
		for (j=1;j<=m;j++)
		{
			if( tm[i][j]=='.' )
			{flag=1;break;}
		}
	}
	
	if (flag)
		printf("Not unique\n");
	else
	{
			for (i=1;i<=n;i++)
	{
		for (j=1;j<=m;j++)
		{
		printf("%c",tm[i][j]);
		}
		printf("\n");
	}

	}
	
	
	
	
	return 0;
	
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值