zoukankan      html  css  js  c++  java
  • SRM DIV2 576 ArcadeManao

    【题意】:找到最短的梯子,使小人儿可以从地面吃到图中的金币。

    【算法】根据Blood Fill的思想想到的算法:
    1.设梯子的长度为i=1
    2.用梯子进行深度优先搜索,判断金币的可达域,
    3.如不能到达地面,i++,继续2;否则return i
    【编码调试BUG】
    1.coin一开始就在最下层的情况,返回0;
     
    【Java代码】来自菜鸟
    import java.util.*;
    import java.util.regex.*;
    import java.text.*;
    import java.math.*;
    
    
    public class ArcadeManao
    {
        boolean[][] tag ;
        int row,col;
        
        public int shortestLadder(String[] level, int coinRow, int coinColumn)
        {
            int ladder=1,i,j;
            row = level.length;
            col = level[0].length();
            tag = new boolean[row][col];
            
            if(coinRow==row)
                return 0;
                
            while(ladder<=50){
                for(i=0;i<row;i++){
                    for(j=0;j<col;j++){
                        tag[i][j]=false;
                    }
                }
                
                if(dfs(level,coinRow-1,coinColumn-1,ladder)==true)
                    break;
                ladder++;
            }
            if(ladder==51)
                ladder=0;
            return ladder;
        }
        
        public boolean dfs(String[] level,int coinRow,int coinColumn,int ladder){
            //right
            if(moveR(level,coinRow,coinColumn,ladder)==true){
                return true;
            }
            //down
            if(moveD(level,coinRow,coinColumn,ladder)==true){
                return true;
            }        
            //left
            if(moveL(level,coinRow,coinColumn,ladder)==true){
                return true;
            }        
            //up
            if(moveU(level,coinRow,coinColumn,ladder)==true){
                return true;
            }        
            return false;
        }
        public boolean moveR(String[] level,int coinRow,int coinColumn,int ladder){
            if(coinColumn>=col-1)
                return false;
            if(level[coinRow].charAt(coinColumn+1)=='X'&&tag[coinRow][coinColumn+1]==false){
                tag[coinRow][coinColumn+1]=true;
                return dfs(level,coinRow,coinColumn+1,ladder);
            }
            return false;
        }
        public boolean moveL(String[] level,int coinRow,int coinColumn,int ladder){
            if(coinColumn<=0)
                return false;
            if(level[coinRow].charAt(coinColumn-1)=='X'&&tag[coinRow][coinColumn-1]==false){
                tag[coinRow][coinColumn-1]=true;
                return dfs(level,coinRow,coinColumn-1,ladder);
            }        
            return false;
        }
        public boolean moveU(String[] level,int coinRow,int coinColumn,int ladder){
            int i=1;
            //find a 'X'
            while(i<=ladder&&(coinRow-i)>=0){
                if(level[coinRow-i].charAt(coinColumn)=='X'&&tag[coinRow-i][coinColumn]==false){
                    //tag
                    tag[coinRow-i][coinColumn]=true;
                    return dfs(level,coinRow-i,coinColumn,ladder);
                }
                i++;
            }        
            return false;
        }
        public boolean moveD(String[] level,int coinRow,int coinColumn,int ladder){
            int i=1;
            //find a 'X'
            while(i<=ladder&&(i+coinRow)<row){
                if(level[coinRow+i].charAt(coinColumn)=='X'&&tag[coinRow+i][coinColumn]==false){
                    //tag
                    tag[coinRow+i][coinColumn]=true;
                    
                    //check if success
                    if(coinRow+i==row-1)
                        return true;
                    return dfs(level,coinRow+i,coinColumn,ladder);
                }
                i++;
            }
            return false;
        }    
        
    
    }
    //Powered by KawigiEdit 2.1.4 (beta) modified by pivanof!

    【Java代码】来自大神

    /**
     * Built using CHelper plug-in
     * Actual solution is at the top
     * @author Egor Kulikov (egor@egork.net)
     */
    public class ArcadeManao {
        public int shortestLadder(String[] level, int coinRow, int coinColumn) {
        int rowCount = level.length;
        int columnCount = level[0].length();
        char[][] map = new char[rowCount][];
        for (int i = 0; i < rowCount; i++)
          map[i] = level[i].toCharArray();
        IndependentSetSystem setSystem = new RecursiveIndependentSetSystem(rowCount * columnCount);
        for (int i = 0; i < rowCount; i++) {
          for (int j = 1; j < columnCount; j++) {
            if (map[i][j] == 'X' && map[i][j - 1] == 'X')
              setSystem.join(i * columnCount + j, i * columnCount + j - 1);
          }
        }
        coinRow--;
        coinColumn--;
        for (int i = 1; i <= rowCount; i++) {
          if (setSystem.get((rowCount - 1) * columnCount) == setSystem.get(coinRow * columnCount + coinColumn))
            return i - 1;
          for (int j = i; j < rowCount; j++) {
            for (int k = 0; k < columnCount; k++) {
              if (map[j][k] == 'X' && map[j - i][k] == 'X')
                setSystem.join(j * columnCount + k, (j - i) * columnCount + k);
            }
          }
        }
        throw new RuntimeException();
        }
    }
     
    interface IndependentSetSystem {
      public boolean join(int first, int second);
     
      public int get(int index);
     
      public static interface Listener {
        public void joined(int joinedRoot, int root);
      }
    }
     
    class RecursiveIndependentSetSystem implements IndependentSetSystem {
      private final int[] color;
      private int setCount;
      private Listener listener;
     
      public RecursiveIndependentSetSystem(int size) {
        color = new int[size];
        for (int i = 0; i < size; i++)
          color[i] = i;
        setCount = size;
      }
     
      public RecursiveIndependentSetSystem(RecursiveIndependentSetSystem other) {
        color = other.color.clone();
        setCount = other.setCount;
      }
     
      public boolean join(int first, int second) {
        first = get(first);
        second = get(second);
        if (first == second)
          return false;
        setCount--;
        color[second] = first;
        if (listener != null)
          listener.joined(second, first);
        return true;
      }
     
      public int get(int index) {
        if (color[index] == index)
          return index;
        return color[index] = get(color[index]);
      }
     
      }

    【C++代码】来自大神

    #include <algorithm> 
    #include <string> 
    #include <vector> 
    #include <queue> 
    #include <iostream> 
    #include <cmath> 
    #include <sstream> 
    #include <map> 
    #include <set> 
    #include <functional> 
    using namespace std; 
    #define pb push_back 
    #define INF 1000000000 
    #define L(s) (int)((s).size()) 
    #define FOR(i,a,b) for (int _n(b), i(a); i <= _n; i++) 
    #define rep(i,n) FOR(i,1,(n)) 
    #define rept(i,n) FOR(i,0,(n)-1) 
    #define C(a) memset((a),0,sizeof(a)) 
    #define ll long long 
    #define mp make_pair 
    #define pii pair<int,int> 
    #define x first 
    #define y second 
    
    bool used[52][52]; 
    inline bool check(vector<string> mas, int ei, int ej, int lad) { 
      --ei; --ej; 
      queue<pii> q; 
      C(used); 
      int n = L(mas); 
      int m = L(mas[0]); 
      used[n - 1][m - 1] = 1; 
      q.push(mp(n - 1, m - 1)); 
      while (!q.empty()) { 
        int ci = q.front().x, cj = q.front().y; 
        q.pop(); 
        if (cj + 1 < m && mas[ci][cj + 1] == 'X' && !used[ci][cj + 1]) { 
          used[ci][cj + 1] = 1; 
          q.push(mp(ci, cj + 1)); 
        } 
        if (cj - 1 >= 0 && mas[ci][cj - 1] == 'X' && !used[ci][cj - 1]) { 
          used[ci][cj - 1] = 1; 
          q.push(mp(ci, cj - 1)); 
        } 
        FOR(di, -lad, lad) { 
          if (ci + di < 0 || ci + di >= n) continue; 
          if (used[ci + di][cj]) continue; 
          if (mas[ci + di][cj] != 'X') continue; 
          used[ci + di][cj] = 1; 
          q.push(mp(ci + di, cj)); 
        } 
      } 
      return used[ei][ej]; 
    } 
    class ArcadeManao  
      { 
        public: 
           int shortestLadder( vector <string> level, int coinRow, int coinColumn ) 
        { 
          rept(ladder, 51) { 
            if (check(level, coinRow, coinColumn, ladder)) return ladder; 
          } 
          return -1; 
        } 
      }; 
    
    
    
    // Powered by FileEdit
    // Powered by moj 4.17 [modified TZTester]
    // Powered by CodeProcessor

    【分析】

      【算法】Graph Theory, Simple Search, Iteration

      【对比】

         1.表示看不懂大神在干什么。Java大神的算法很奇怪。C++大神的算法貌似和我同源,但是好难读懂,各种宏定义。

         2.菜鸟的代码可读性还可以,但是递归的实现方式捉急,如果采用堆栈的方式会更好。或者采用BFS的队列来实现也可以啊。

         3.学习Java大神的这三行代码,可以很轻松地将字符串数组转换成一个字符矩阵。

    char[][] map = new char[rowCount][]; 
    for (int i = 0; i < rowCount; i++)
          map[i] = level[i].toCharArray();

      【总结】

        1.见识了Blood Fill

        2.根据ladder的长度,采用Blood Fill的思想来求可达域,这个算法还是挺优雅的。

        

  • 相关阅读:
    深入理解link和@import到底有什么区别?
    你应该知道的简单易用的CSS技巧
    META标签的设置
    前端webp图片
    PAT 1130 Infix Expression[难][dfs]
    PAT 1118 Birds in Forest [一般]
    生信-cufflinks输入输出文件分析
    PAT 1121 Damn Single[简单]
    PAT 1049 Counting Ones [难]
    NGS中的一些软件功能介绍
  • 原文地址:https://www.cnblogs.com/wang3/p/3216896.html
Copyright © 2011-2022 走看看