Curling 2.0

文章描述了一种名为G-Curling2.0的冰壶游戏,规则与传统冰壶不同,玩家需将石头从起点移动到目标点,最少次数。通过深度优先搜索(DFS)算法可以找到从起点到目标的最短路径,同时考虑了游戏规则,如碰撞、出界和限制移动次数。题目提供了输入输出示例,并给出了C++代码实现的思路。
摘要由CSDN通过智能技术生成

G - Curling 2.0

On Planet MM-21, after their Olympic games this year, curling is getting popular. But the rules are somewhat different from ours. The game is played on an ice game board on which a square mesh is marked. They use only a single stone. The purpose of the game is to lead the stone from the start to the goal with the minimum number of moves.

Fig. 1 shows an example of a game board. Some squares may be occupied with blocks. There are two special squares namely the start and the goal, which are not occupied with blocks. (These two squares are distinct.) Once the stone begins to move, it will proceed until it hits a block. In order to bring the stone to the goal, you may have to stop the stone by hitting it against a block, and throw again.


Fig. 1: Example of board (S: start, G: goal)

The movement of the stone obeys the following rules:

  • At the beginning, the stone stands still at the start square.
  • The movements of the stone are restricted to x and y directions. Diagonal moves are prohibited.
  • When the stone stands still, you can make it moving by throwing it. You may throw it to any direction unless it is blocked immediately(Fig. 2(a)).
  • Once thrown, the stone keeps moving to the same direction until one of the following occurs:
    • The stone hits a block (Fig. 2(b), (c)).
      • The stone stops at the square next to the block it hit.
      • The block disappears.
    • The stone gets out of the board.
      • The game ends in failure.
    • The stone reaches the goal square.
      • The stone stops there and the game ends in success.
  • You cannot throw the stone more than 10 times in a game. If the stone does not reach the goal in 10 moves, the game ends in failure.


Fig. 2: Stone movements

Under the rules, we would like to know whether the stone at the start can reach the goal and, if yes, the minimum number of moves required.

With the initial configuration shown in Fig. 1, 4 moves are required to bring the stone from the start to the goal. The route is shown in Fig. 3(a). Notice when the stone reaches the goal, the board configuration has changed as in Fig. 3(b).


Fig. 3: The solution for Fig. D-1 and the final board configuration

Input

The input is a sequence of datasets. The end of the input is indicated by a line containing two zeros separated by a space. The number of datasets never exceeds 100.

Each dataset is formatted as follows.

the width(=w) and the height(=h) of the boardFirst row of the board
...h-th row of the board

The width and the height of the board satisfy: 2 <= w <= 20, 1 <= h <= 20.

Each line consists of w decimal numbers delimited by a space. The number describes the status of the corresponding square.

0vacant square
1block
2start position
3goal position

The dataset for Fig. D-1 is as follows:

6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1

Output

For each dataset, print a line having a decimal integer indicating the minimum number of moves along a route from the start to the goal. If there are no such routes, print -1 instead. Each line should not have any character other than this number.

Sample

InputcopyOutputcopy
2 1
3 2
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1
6 1
1 1 2 1 1 3
6 1
1 0 2 1 1 3
12 1
2 0 1 1 1 1 1 1 1 1 1 3
13 1
2 0 1 1 1 1 1 1 1 1 1 1 3
0 0
1
4
-1
4
10
-1

中文:

Descriptions:

今年的奥运会之后,在行星mm-21上冰壶越来越受欢迎。但是规则和我们的有点不同。这个游戏是在一个冰游戏板上玩的,上面有一个正方形网格。他们只用一块石头。游戏的目的是让石子从起点到终点,并且移动的次数最小

图1显示了一个游戏板的例子。一些正方形格子可能被砖块占据。有两个特殊的格子,起始点和目标点,这是不占用块。(这两个方块是不同的)一旦石头开始移动就不会停下,除非它击中砖块块。为了使石头到达终点,你可以通过让石块击中墙壁或者砖块来停下。

图1:例子(S:开始,G:目标)

石头的运动遵循以下规则:

  • 开始时,石头静止起点广场上。
  • 石头的运动仅限于x和y方向。禁止对角线移动。
  • 当石头静止时,你可以让他向任意方向移动,除非它移动的方向上有砖块(图2(a))。
  • 一旦抛出,石头不断向同一方向移动,直到下列事件之一发生:
    • 石头击中砖块(图2(b),(c))。.
      • 石头停在他击中的砖块之前
      • 被击中的砖块消失
    • 石块飞出游戏板之外。
      • 游戏结束的条件
    • 到达目标点
      • 石头停在目标点游戏成功
  • 不能在十步之内到达目标点则返回失败。

Fig. 2: Stone movements

通过这些规则我们想知道,石头是否能够到达目标点和最少移动次数

初始配置如图1所示,石头从开始到目标需要4次移动。路线如图3所示(a)。注意当石头到达目标时,游戏版的配置如图3(b)改变。

图3:图1的解决方案和解决之后的结果。

Input

输入是一组数据。输入结束标志为两个0。数据组的数量不超过100。

每个数据集如下展示

板的宽度(w)和高度(h) 
游戏版的第一行 
... 
游戏版的h-th行

版的宽和高满足: 2 <= w <= 20, 1 <= h <= 20.

每行由一个空格分隔的十进制数字组成。该数字描述相应的格子的状态。

1 砖块

2 开始点

3 目标点

图. D-1数据如下:

6 6 
1 0 0 2 1 0 
1 1 0 0 0 0 
0 0 0 0 0 3 
0 0 0 0 0 0 
1 0 0 0 0 1 
0 1 1 1 1 1

Output

对于每个数据,打印一个十进制整数的行,表示从开始到目标的路径的最小移动次数。如果没有这样的路线,打印- 1。每个行不应该有这个数字以外的任何字符。

Sample Input

2 1
3 2
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1
6 1
1 1 2 1 1 3
6 1
1 0 2 1 1 3
12 1
2 0 1 1 1 1 1 1 1 1 1 3
13 1
2 0 1 1 1 1 1 1 1 1 1 1 3
0 0

Sample Output

1
4
-1
4
10
-1

题解:

很明显的,dfs搜索,但是方向数组(一开始是一格一格走的现在改为一条一条走(个人觉得好像就是这么一点区别)),然后呢,就是注意一下条件的判断加上回溯和剪枝就行啦!

上代码!!!

#include<iostream>
using namespace std;
int m[30][30];
int w, h;
int ans = 100;
int dx[] = { 1,-1,0,0 };
int dy[] = { 0,0,1,-1 };//方向数组
void dfs(int x, int y,int t)
{
	if (m[x][y] == 3)//终点
	{
		ans = min(t, ans);
		return;
	}
	if (t >= 10 || t >ans)
		return;//剪枝,减少没必要的递归
	for (int i = 0; i < 4; i++)
	{
		int x1 = x + dx[i];
		int y1 = y + dy[i];
		if (m[x1][y1] == 1||x1<1||y1<1||x1>h||y1>w)//不能走的情况
			continue;
		while (x1 >=1 && x1 <= h&& y1 >=1 && y1 <= w && m[x1][y1] != 1)
		{
			if (m[x1][y1] == 3)//到终点的情况
			{
				t++;
				ans = min(t, ans);
				return;
			}
				x1 += dx[i];
				y1 += dy[i];//没到终点就一直走
		}
		if (x1<1 || y1<1 || x1>h || y1>w)//出界
			continue;
		t++;
		m[x1][y1] = 0;//撞墙了,墙破
		dfs(x1-dx[i], y1-dy[i], t);
		t--;
		m[x1][y1] = 1;//回溯
	}
}
int main()
{
	int x = 0;
	int y = 0;
	for (;;)
	{
		cin >> w >> h;
		if (h == 0 && w == 0)
			break;
		else
			for (int i = 1; i <= h; i++)
			{
				for (int j = 1; j <= w; j++)
				{
					cin >> m[i][j];
					if (m[i][j] == 2)//起点的位置
					{
						x = i;
						y = j;
					}
				}
			}
		dfs(x, y, 0);
		if (ans > 10)
			ans = -1;
		cout << ans << endl;
		ans = 100;
		for (int i = 1; i <= h; i++)
		{
			for (int j = 1; j <= w; j++)
				m[i][j] = 0;//初始化数组
		}
	}
	return 0;
}

最后的最后,祝各位题题ac,比赛ak!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值