• poj3009 Curling 2.0


    题目

    一场冰面比赛在一个矩形区域进行,区域上设置有障碍(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
    ", 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
    ");
            else printf("%d
    ", steps);
        }
    }
    
  • 相关阅读:
    Docker系列【Docker中启动flowable查看流转日志时字体显示方框问题】
    常用功能系列【hutool生成验证码】
    注册表立即生效命令
    DataX Kettle 使用场景的对比
    图片查看器.reg
    mysql error :1114 The table ‘XXX‘ is full
    常用用时
    MySQL 之 SQL Modes
    生产环境迁移至预发布环境
    MySQL:[Err] 1292 Incorrect datetime value: ‘00000000 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
  • 原文地址:https://www.cnblogs.com/patrolli/p/12188880.html
Copyright © 2020-2023  润新知