Curling 2.0

本文介绍了一个基于网格的游戏Curling2.0,玩家需要通过精确投掷来移动石头,使其从起点到达终点,同时尽可能消除路径上的障碍。文章详细解释了游戏规则,并提供了两种不同的代码实现方案,帮助读者理解如何使用深度优先搜索算法解决这个问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


B - Curling 2.0
Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u   

Description

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 board
    First 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

  • 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 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 
  • 深度深度
  •  

深度优先搜索,题目大意就是,有一个起始点2 有一个终点3 0表示空地 1表示墙 一开始你站在起始点扔石头
可以向上下左右四个方向扔,确定方向后,如果就在你一步远的地方是墙的话就不能扔 不是墙就能扔,扔出去的石头能够飞到无限远(如果飞过了边界,就不在飞回来,然后永远达不到终点),如果你的石头遇到了墙,就在到达墙前面的一步停下,然后墙消失。给定数据,问从起点到终点的最小扔石头次数(飘过终点就算达到终点)
这道题,我代码写糟了,bug不好找,因此发来谨记,这是最后一次,先判断在到达点进行dfs
我的,判断之后dfs(边界容易被上次数据影响从而影响正确结果,就因为没有清空数组,导致wa2)
//
// Create by 神舟 on 2015-02-20
//

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

#define CLR(x) memset(x,0,sizeof x)
#define ll long long
#define inf 0x3f3f3f3f
const int maxn=2e1+5;
const int MOD=5e5+5;
int n,m,ans;
int num[maxn][maxn],dir[4][2]={1,0,0,1,-1,0,0,-1};
void dfs(int step, int I,int J)
{
    if(step>9||step>=ans) return;//剪枝
    for(int i=0;i<4;i++){
        int i1=I,j1=J,flag1=0,flag2=0;//flag1和flag2必须都等于1的时候,才能进行深度优先搜索
        while(i1+dir[i][0]>=1&& i1+dir[i][0]<=n&&j1+dir[i][1]>=1&&j1+dir[i][1]<=m&&num[i1+dir[i][0]][j1+dir[i][1]] != 1){//先判
            flag1=1;//表示并非一开始就一堵墙 ,堵到在
            i1+=dir[i][0],j1+=dir[i][1];
            if(num[i1][j1]==3){//飞过终点
                ans=min(ans,step+1);
                return;
            }
        }
        if(num[i1 + dir[i][0]][j1 + dir[i][1]] == 1)
            flag2=1;
        if(flag2&&flag1){
           // printf("%d  %d\n",i1,j1);
            num[i1+dir[i][0]][j1+dir[i][1]]=0;
            dfs(step+1,i1,j1);
            num[i1+dir[i][0]][j1+dir[i][1]]=1;
        }
    }
}
int main()
{
#ifdef LOCAL
 freopen("in.txt","r",stdin);
 //freopen("out.txt","w",stdout);
#endif
 ios_base::sync_with_stdio(0);
 while(scanf("%d%d",&m,&n)!=EOF&&n&&m){
        CLR(num);//******清零,就这一句话,天差地别
        for(int i=1;i<=n;i++) for(int j=1;j<=m;scanf("%d",num[i]+j++));
        ans=inf;
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(num[i][j]==2){
            dfs(0,i,j);
        }
        if(ans>10) ans=-1;
        printf("%d\n",ans);
        //printf("\n\n\n");
 }
 return 0;
}

韬韬的:
//
//  POJ 3009 Curling 2.0
//
//  Created by TaoSama on 2015-02-19
//  Copyright (c) 2014 TaoSama. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
#define CLR(x,y) memset(x, y, sizeof(x))

using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

int n, m, d[4][2] = { -1, 0, 1, 0, 0, 1, 0, -1};
char a[105][105];
int sx, sy, gx, gy, ans;//有的变量没用的。。。不要太在意 ans是最后答案
void dfs(int x, int y, int seg) {
 if(seg > 10 || seg >= ans) return;//剪枝
 for(int i = 0; i < 4; ++i) {
  for(int j = 1;; ++j) {//for实现和我while一样的功能
   int nx = x + j * d[i][0], ny = y + j * d[i][1];//管它三七21,先加上再判断这样就不会因为边界受上次影响而出错了
   if(nx < 1 || nx > n || ny < 1 || ny > m) break;//越界
   if(a[nx][ny] == '3') {
    ans = min(ans, seg + 1);//飞过终点
    return;
   }
   if(a[nx][ny] == '1') {//遇到墙
    if(j == 1) break;//如果是人 面前一步那堵墙,
    a[nx][ny] = '0';//拆墙
    nx -= d[i][0], ny -= d[i][1];
    dfs(nx, ny, seg + 1);
    nx += d[i][0], ny += d[i][1];
    a[nx][ny] = '1';//补墙
    break;
   }
  }
 }
}
int main() {
#ifdef LOCAL
 freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
 ios_base::sync_with_stdio(0);

 while(cin >> m >> n && n != 0 && m != 0) {
  for(int i = 1; i <= n; ++i) {
   for(int j = 1; j <= m; ++j) {
    cin >> a[i][j];
    if(a[i][j] == '2')
     sx = i, sy = j;
    if(a[i][j] == '3')
     gx = i, gy = j;
   }
  }
  ans = INF;
  dfs(sx, sy, 0);
  if(ans > 10) ans = -1;
  cout << ans << endl;
 }
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值