Curling 2.0

Curling 2.0

在MM-21星球上,今年的奥运会之后,冰壶越来越受欢迎。但规则与我们的规则有些不同。游戏在冰游戏板上进行,游戏板上标有方形网格。他们只使用一块石头。游戏的目的是以最少的动作将石头从开始引导到目标。

图1示出了游戏板的示例。一些正方形可能被块占用。有两个特殊的方块,即开始和目标,没有被块占用。(这两个方块是截然不同的。)一旦石头开始移动,它将继续运行,直到它碰到一个块。为了将石头带到目标,你可能不得不通过击打一块来阻止石头,然后再扔。

werwerwer
图1:电路板示例(S:开始,G:目标)

石头的运动遵循以下规则:
● 起初,石头静止在起始广场。
● 石头的运动受限于x和y方向。禁止对角线移动。
● 当石头静止不动时,你可以通过扔它来移动它。你可以把它扔到任何方向,除非它立即被阻止(图2(a))
● 一旦抛出,石头就会向同一方向移动,直到出现下列情况之一:
  ○ 石头击中一个块(图2(b),(c))。
    ◾ 石头停在它撞击的街区旁边的方块上。
    ◾ 块消失了。
  ○ 石头离开了游戏板。
    ◾ 游戏以失败告终。
  ○ 石头到达目标块。
    ◾ 石头停在那里,游戏成功结束。
● 你不能在游戏中扔石头超过10次。如果石头在10次移动中没有达到目标,则游戏以失败告终。
在这里插入图片描述
               图2:石头运动

根据规则,我们想知道一开始的石头是否能达到目标,如果是,则需要求出最小的移动次数。

使用图1所示的初始配置,需要4次移动才能使石头从头到尾。路线如图3(a)所示。注意当石头到达目标时,板的配置已经改变,如图3(b)所示。
在这里插入图片描述
      图3:图D-1的解决方案和最终的板配置

Input

输入是一系列数据集。输入的结尾由包含两个由空格分隔的零的线表示。数据集的数量永远不会超过100。
每个数据集的格式如下。

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

板的宽度和高度满足:2 <= w <= 20,1 <= h <= 20。

每行包含由空格分隔的w十进制数。该数字描述了相应方块的状态。

0	空置方块
1	块
2	开始的位置
3	目标位置

图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 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

C++编写:

这道题也是深度优先搜索.

//w表示列数,h表示行数
#include<iostream>
using namespace std;
const int MAX=20;
int board[MAX+1][MAX+1];
int sx,sy;          //用于记录起点坐标
int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int w,h,steps;     //steps为最小移动次数

bool check(int x,int y)
{
    if(x>=0 && x<h && y>=0 &&y<w)   return 1;
    else    return 0;
}

void dfs(int x,int y,int step)
{
    for(int i=0;i<4;i++)
    {
        int nx=x+dx[i],ny=y+dy[i];
        int nx1,ny1;
        if(step<steps-1 && check(nx,ny) && board[nx][ny]!=1)    
        {
            while(check(nx,ny)&&board[nx][ny]==0)
            {
                nx += dx[i];
                ny += dy[i];
            }
            if(check(nx,ny))
            {
                if(board[nx][ny] == 3)
                    steps=step+1;
                if(board[nx][ny] == 1)
                {
                    board[nx][ny] = 0;
                    dfs(nx-dx[i],ny-dy[i],step+1);
                    board[nx][ny] = 1;
                }
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    while(cin>>w>>h)
    {
        if(w==0 && h==0)
        break;
        steps = 11;
        for(int i=0;i<h;i++)
        {
            for(int j=0;j<w;j++)
            {
                cin>>board[i][j];
                if(board[i][j] == 2)     //记录起点坐标
                {
                    sx=i;
                    sy=j;
                    board[i][j]=0;      //将起点坐标的值换成0
                }
            }
        }
        dfs(sx,sy,0);
        steps=steps<11?steps:-1;
        cout<<steps<<endl; 
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值