码迷,mamicode.com
首页 > Web开发 > 详细

poj3009 Curling 2.0

时间:2020-01-13 20:19:31      阅读:107      评论:0      收藏:0      [点我收藏+]

标签:运动   namespace   注意   input   first   cpp   空格   point   表示   

题目

一场冰面比赛在一个矩形区域进行,区域上设置有障碍(1表示),空白区域(0表示),起点(2表示),终点(3表示)。起始在起点有一个石头,每次将它向上左下右四个方向之一抛出(当某一方向上临近有障碍时不能向这一方向抛出),石块将沿这一方向运动,直到:

  • 石头撞到了障碍:石头停在靠近障碍的那个空格上,障碍消失
  • 石头超出了矩形区域的范围,这次抛出无效
  • 到达终点

一局游戏一共可以抛掷石头10次,如果10次后石头还没有到达终点,那么游戏失败。需要到达终点的最少抛掷次数。

样例输入

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

思路

  • _throw()函数模拟每次石头向某一方向运动,返回三种结果:出界、到达终点、遇到障碍。
  • 根据抛出的三种结果,出界则转向下一方向尝试,到达终点则更新最终步数,遇到障碍则继续递归到新一状态,从这一状态开始重新将石头向四个方向扔出。注意保留现场。

代码

#include <iostream>
#include <utility>
using namespace std;
typedef pair<int, int> PII;
const int N = 22;
const int dr[] = {0, 1, -1, 0};
const int dc[] = {1, 0, 0, -1};
int m, n;
int end_r, end_c; //终点的坐标
int g[N][N];
int cnt, steps;

int _throw(int start_r, int start_c, int dir, PII &end_point){
    int raw = start_r, col = start_c;
    while(1){
        raw += dr[dir];
        col += dc[dir];
    //   printf("cur_r: %d cur_c: %d\n", raw, col);
        if(raw < 0 || raw >= m || col < 0 || col >= n){ // outside
            end_point.first = start_r;
            end_point.second = start_c;
            return 0;
        }
        if(raw == end_r && col == end_c){  //arrive the end point
            return 1;
        }
        if(g[raw][col] == 1){     //arrive a block
            end_point.first = raw - dr[dir];
            end_point.second = col - dc[dir];
            return 2;
        }
    }
}

void dfs(int start_x, int start_y){
    if(cnt > 10) return;
    int condition;
    for(int dir = 0; dir < 4; ++dir){
        PII end_point;
        end_point.first = start_x; end_point.second = start_y;
        int tmpr = start_x + dr[dir];
        int tmpc = start_y + dc[dir];                //用于判断“起点”四周是否有障碍阻挡抛出
        if(tmpr>=0 && tmpr<m && tmpc>=0 && tmpc < n && g[tmpr][tmpc] != 1){ //当四周没有blocks时可以throw
            condition = _throw(start_x, start_y, dir, end_point);
            if(condition == 0) continue;
            if(condition == 1){ //到达终点
                if(cnt+1 < steps) {steps  = cnt+1;} //更新最少到达的结果到steps中
                continue;
            }
            if(condition == 2) {    
                int old_cnt = cnt;  //保留当前状态的步数
                cnt++;
                g[end_point.first+dr[dir]][end_point.second+dc[dir]] = 0; //清除障碍
                dfs(end_point.first, end_point.second); //进入下一状态
                g[end_point.first+dr[dir]][end_point.second+dc[dir]] = 1; //恢复现场
                cnt = old_cnt;
            }
        }
    }
}

int main(){
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    int start_r, start_c;
    while(scanf("%d%d", &n, &m) && m != 0){
        for(int i = 0; i < m; ++i){
            for(int j = 0; j < n; ++j){
                scanf("%d", &g[i][j]);
                if(g[i][j] == 2){ start_r = i; start_c = j;}
                if(g[i][j] == 3) { end_r = i; end_c = j;}
            }
        } 
        
        cnt = 0, steps = 100000;
        dfs(start_r, start_c);
        if(steps>10) printf("-1\n");
        else printf("%d\n", steps);
    }
}

poj3009 Curling 2.0

标签:运动   namespace   注意   input   first   cpp   空格   point   表示   

原文地址:https://www.cnblogs.com/patrolli/p/12188880.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!