HDU 4770 模拟题

题意:

给定n*m的地图

问用L型能否覆盖所有 .

且不允许覆盖到*

L型形如:

*

**

可以允许一个L 旋转

 

思路:

二进制枚举所有状态

因为只有15个.

 

 

#include<string.h>
#include<stdio.h>
#include<queue>
using namespace std;
inline int Max(int a,int b){return a>b?a:b;}
inline int Min(int a,int b){return a<b?a:b;}
#define N 250
#define inf 10000000
int n,m;
struct node{
	int x, y;
}hehe[20];
int all;
bool map[N][N];
int vis[N][N];
int Stack[20],top;
int abs(int x){return x>0?x:-x;}
bool Inmap(int x,int y){
	if(x>=n || x<0 || y>=m || y<0)return false;
	return true;
}
bool hao(node a,node b){
	int len = abs(a.x-b.x)+abs(a.y-b.y);
	if(len>2)return false;

	if(a.y==b.y)
	{
		if(len == 2)return false;
		if(!Inmap(a.x, a.y+1) || map[a.x][a.y+1])return true;
		if(!Inmap(a.x, a.y-1) || map[a.x][a.y-1])return true;

		if(!Inmap(b.x, b.y+1) || map[b.x][b.y+1])return true;
		if(!Inmap(b.x, b.y-1) || map[b.x][b.y-1])return true;
		return false;
	}
	if(a.x==b.x)
	{
		if(len == 2)return false;
		if(!Inmap(a.y, a.x+1) || map[a.y][a.x+1])return true;
		if(!Inmap(a.y, a.x-1) || map[a.y][a.x-1])return true;

		if(!Inmap(b.y, b.x+1) || map[b.y][b.x+1])return true;
		if(!Inmap(b.y, b.x-1) || map[b.y][b.x-1])return true;
		return false;
	}
	if(a.x<b.x)
	{
		if(!Inmap(a.x-1,a.y) || map[a.x-1][a.y])	return true;
		if(!Inmap(a.x+1,a.y) || map[a.x+1][a.y])	return true;
		return false;
	}
	else 
	{
		if(!Inmap(a.x, a.y-1) || map[a.x][a.y-1]) return true;
		if(!Inmap(a.x, a.y+1) || map[a.x][a.y+1]) return true;
		return false;
	}
}
bool hao3(node a,node b,node c){
	if(a.x == b.x && a.x == c.x)return false;
	if(a.y == b.y && a.y == c.y)return false;
	int lala[3];
	lala[0] = abs(a.x-b.x)+abs(a.y-b.y);
	lala[1] = abs(a.x-c.x)+abs(a.y-c.y);
	lala[2] = abs(c.x-b.x)+abs(c.y-b.y);
	return lala[0]+lala[1]+lala[2] == 4;
}
bool hao1(node e){
	if(!Inmap(e.x-1,e.y) || map[e.x-1][e.y])
	{
		if(!Inmap(e.x,e.y-1) || map[e.x][e.y-1])return true;
		if(!Inmap(e.x,e.y+1) || map[e.x][e.y+1])return true;
	}
	else if(!Inmap(e.x+1,e.y) || map[e.x+1][e.y])
	{
		if(!Inmap(e.x, e.y+1) || map[e.x][e.y+1])return true;
		if(!Inmap(e.x, e.y-1) || map[e.x][e.y-1])return true;
	}
	return false;
}
int main(){
	int i, j;

	while(scanf("%d %d",&n,&m), n){
		all = 0;
		for(i=0;i<n;i++)
		{
			char s[N];scanf("%s",s);
			for(j=0;j<m;j++)
				if(s[j] == '#')map[i][j] = false;
				else {
					map[i][j] = true;
					hehe[all].x = i;
					hehe[all].y = j;
					all++;
				}
		}
		if(all == 0){printf("0\n");continue;}
		int maxx = (1<<all)-1, ans = 10000;
		for(i=0;i<=maxx;i++)
		{
			int num = 0;
			for(j=0;j<all;j++)vis[ hehe[j].x ][hehe[j].y] = 0;
			bool ok = true;

			for(j = 0;j<all;j++)
				if(i & (1<<j))
				{
					vis[hehe[j].x][hehe[j].y] = 1;
					if(Inmap(hehe[j].x-1, hehe[j].y) && map[hehe[j].x-1][hehe[j].y] == false){ok = false;break;}
					vis[hehe[j].x-1][hehe[j].y] = 1;
					if(Inmap(hehe[j].x, hehe[j].y+1) && map[hehe[j].x][hehe[j].y+1] == false){ok = false;break;}

					vis[hehe[j].x][hehe[j].y+1] = 1;
					num++;
				}
				if(ok == false)continue;
				top = 0;
				for(j=0;j<all;j++)
					if(vis[ hehe[j].x ][hehe[j].y] == 0){ok = false; Stack[top++] = j;}
					if(ok){ans = Min(ans, num); continue;}

					if(top>3)continue;
					if(top==3)
					{if(!hao3(hehe[ Stack[0] ], hehe[Stack[1]], hehe[Stack[2]]))continue;}
					else if(top == 2)
					{if(!hao(hehe[Stack[0]], hehe[Stack[1]]))continue;}
					else 
					{
						if(!hao1(hehe[Stack[0]]))continue;
					}
					ans = Min(ans, num+1);
		}
		if(ans == 10000)ans = -1;
		printf("%d\n",ans);
	}
	return 0;
}
/*
2 2
##
##
2 3
#..
..#
3 3
###
#.#
###

4 2
#.
..
.#
..
1 1
.
2 1
.
#
1 2
#.
1 5
.#...
1 4
.#..
2 5
...#.
####.

6 4
#.##
..#.
#.#.
#..#
....
....

5 5
#..#.
##.#.
####.
#.###
#..##

2 2
..
#.
2 2
..
..
2 2
##
.#
2 2
##
#.

2 3
###
#..
2 3
#.#
#.#

*/


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值