poj3009(好久不见)

不知不觉,有两个月没写博客了。惭愧。。。

好久不练,果然手生,今天做了一题,搞了一个多小时,各种问题。

题目意思很简单,一个图一个起点一个终点,中间有些block阻碍,可以向上下左右扔球,求从起点到终点最少扔多少次。

 

扔的规则,如果周围靠着阻碍,不能扔,如果没有,那么可以扔,碰到阻碍,阻碍消失,球停在那里。如果那个方向一个阻碍都没有,那么就game over。

 

最关键是最多扔10次,这也是我第一次提交TLE没注意的地方,不用搜索那么多次,10次够了。

 

虽然是简单的搜索,但是还是有很多注意的地方。这里就不多说了,直接上代码,继续努力。

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int w, h, ans;
int board[25][25];
typedef struct point
{
	int x, y;
}Point;
Point start, end;
bool flag = false;
int min = 0x0FFFFFFF;
//判断是否到终点
bool IsOver(Point now)
{
	if (now.x == end.x)
	{
		int s = now.y < end.y ? now.y : end.y;
		int e = now.y > end.y ? now.y : end.y;
		for (int i = s + 1; i < e; ++ i)
		{
			if (board[now.x][i] != 0)
			{
				return false;
			}
		}
		return true;
	}
	else if(now.y == end.y)
	{
		int s = now.x < end.x ? now.x : end.x;
		int e = now.x > end.x ? now.x : end.x;
		for (int i = s + 1; i < e; ++ i)
		{
			if (board[i][now.y] != 0)
			{
				return false;
			}
		}
		return true;
	}
	else
	{
		return false;
	}

}
void dfs(Point now)
{
	//ans ++;
	if (ans > 9)
	{
		return;
	}
	if (IsOver(now))
	{
		//printf("%d\n", ans);
		if (min > ans)
		{
			min = ans;
		}
		flag = true;
		return;
	}
	
	Point tmp;
	//down
	if (now.x + 1 <= h && ! board[now.x + 1][now.y])
	{
		for (int i = now.x + 2; i <= h; ++ i)
		{
			if (board[i][now.y])
			{
				ans ++;
				tmp.x = i - 1;
				tmp.y = now.y;
				board[i][now.y] = 0;
				dfs(tmp);
				board[i][now.y] = 1;
				ans --;
				break;
			}
		}
	}
	//right
	if (now.y + 1 <= w && ! board[now.x][now.y + 1])
	{
		for (int j = now.y + 2; j <= w; ++ j)
		{
			if (board[now.x][j])
			{
				ans ++;
				tmp.x = now.x;
				tmp.y = j - 1;
				board[now.x][j] = 0;
				dfs(tmp);
				board[now.x][j] = 1;
				ans --;
				break;
			}
		}
	}
	//up
	if (now.x - 1 >= 1 && ! board[now.x - 1][now.y])
	{
		for (int i = now.x - 2; i >= 1; -- i)
		{
			if (board[i][now.y])
			{
				ans ++;
				tmp.x = i + 1;
				tmp.y = now.y;
				board[i][now.y] = 0;
				dfs(tmp);
				board[i][now.y] = 1;
				ans --;
				break;
			}
		}
	}
	//left
	if (now.y - 1 >= 1 && ! board[now.x][now.y - 1])
	{
		for (int j = now.y - 2; j >= 1; -- j)
		{
			if (board[now.x][j])
			{
				ans ++;
				tmp.x = now.x;
				tmp.y = j + 1;
				board[now.x][j] = 0;
				dfs(tmp);
				board[now.x][j] = 1;
				ans --;
				break;
			}
		}
	}
	return;//printf("-1\n");
}
int main()
{
	while (1)
	{
		scanf("%d %d", &w, &h);
		if (w == 0 && h == 0)
		{
			break;
		}
		ans = 0;
		flag = false;
		min = 0x0FFFFFFF;
		memset(board, 1, sizeof(board));
		for (int i = 1; i <= h; ++ i)
		{
			for (int j = 1; j <= w; ++ j)
			{
				scanf("%d", &board[i][j]);
				if (board[i][j] == 2)
				{
					start.x = i;
					start.y = j;
					board[i][j] = 0;
				}
				else if (board[i][j] == 3)
				{
					end.x = i;
					end.y = j;
				}
			}
		}
		dfs(start);
		if (!flag || min > 9)
		{
			printf("-1\n");
		}
		else
			printf("%d\n", min + 1);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值