[プログラマー]ロックとキー

27418 ワード

  • の大きさが20なので、完全に探索できます.
  • ロックはn、キーはmは
  • 200 x 200 x 4の場合.(各キーを1つのスペースに移動してボリューム化すると、nxnx 4の場合があります)
  • でもnはせいぜい20なので、完全に探索しても大丈夫です.
  • n、mは最大20なので、メモリにもいいです.
  • 4種類の鍵でも作れます.
  • 錠:NxN正方形、溝(0)、回転(10)
  • キー/;MxM.正方形->回転可能、移動可能->ロックの溝!「(0)」は「鍵の回転(1)」と完全に一致する.
  • 「鍵の回転」が「鍵の回転」に遭遇したときX!!
  • 「すべての溝をロック」を充填し、「空いている場所がない」ことを確認します.
  • 「錠」領域の外では、「鍵の溝、突起」は開錠に影響しないが、「鍵の突起」は「錠の突起」だけに重なることはできない.

  • 回転

  • int[][][] gkey = new int[m][m][4];

  • ここでは、0度、90180度、270度のキー形状を記憶する.

  • Rotation実装は以下のことができる.
    -この方法には、独立したメモリを使用するという欠点があります.どうせこの問題は各形状を保存して解決する必要があるので、大丈夫だと思います.


  • Convolve

  • 初期の考え方


  • Paddingに参加するのがもっと便利な方法です


  • 1は突起です.0がメイン

  • 鍵の0には鍵の1が含まれている必要があります->1

  • 鍵の1には鍵の0が含まれている必要があります.->1 ..

  • 鍵の0は鍵の0があって、あるいは鍵の1は鍵の1がありません

  • この場合XOR
  • 0 ,1 —> 1
  • 1, 0 —> 1
  • 1, 1 —> 0
  • 0 ,0 —> 0
  • 、つまり0は表示されません.->0が存在する場合はfalseです.そうでなければtrueを返します.->したがって、lockのすべての要素が1であってもtrueが返されます.

  • Convolutionの実現方法いっそ大きな2次元配列を割り当てて解いたほうがいい.
  • サイズ:2 M+n-2.
  • の間にロック->row:m-1~m+n-2を置き、colも同様です.
  • キーと畳み込むたびに、中央ロックを初期化する必要があります.

  • 以下に、コード->Runtime Errorを記述する小さな理由を示します.理由は….下
  • package test;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.StringTokenizer;
    
    public class main {
        public static int n,m;
        public static int[][] glock;
        public static int[][][] gkey;
    
        public static void setKey(){
    
            // 90도씩 회전시켜
            // i 번째 도형을 회전시켜 저장한다.
            /*
            * row --> col.lengt() - row 로 변환된다.
            * 어차피 각자의 memory를 이미 차지하고 있기 때문에.
            * */
            for(int i=0;i<3;i++){
                for(int r =0;r<m;r++){
                    for(int c=0;c<m;c++){
                        gkey[i+1][c][m-1-r] = gkey[i][r][c];
                    }
                }
            }
    
        }
        public static boolean solution(int[][] key, int[][] lock) {
            boolean answer = false;
            n = lock.length;
            m = key.length;
            glock = lock;
            // key를 ......
            gkey = new int[4][m][m];
            // 첫 번째 모양을 세팅
            for(int r=0;r<lock.length;r++){
                for(int c =0;c<lock[0].length;c++){
                    gkey[0][r][c]= key[r][c];
                }
            }
            setKey();
            answer = convolve();
    
            return answer;
        }
    
        public static boolean convolve(){
            int len = 2*m+n-2; // 7
            int[][] sheet = new int[len][len];
    
            int row = m-1, col = m-1;
            for(int key=0;key<4;key++) {
                // 맨 왼쪽 맨 위부터 key를 연산시킨다.전체를 XOR 연산 시키더라도, 마지막에는 중앙의 것만 확인하면 된다.
                for (int r = 0; r <= len-m; r++) {
                    for (int c = 0; c <= len-m; c++) {
                        // 시트를 초기화 =====
                        // 중앙에 key를 재배치한다.(그 바깥은 상관 없다 ) --> 출력해 보니, 초기화는 잘된 거 맞음.
                        for(int lr=0;lr<n;lr++){
                            for(int lc=0;lc<n;lc++){
                                sheet[row+lr][col+lc]=glock[lr][lc];
                            }
                        }
                        // 매 번 (r,c)를 key 의 왼쪽 맨 위 꼭지점이라고 생각을 한다.
                        for(int kr=0;kr<m;kr++){
                            for(int kc=0;kc<m;kc++){
                                sheet[r+kr][c+kc] =(sheet[r+kr][c+kc] ^ gkey[key][kr][kc]);
                            }
                        }
                        // 해당 convolution 결과, 중앙의 key에 0 이 없다면 --> 성공이다
                        if(isLockOpen(sheet)) return true;
                    }
                }
            }
            return false;
    
        }
    
        public static boolean isLockOpen(int[][] sheet){
            int row = m-1, col = m-1;
            // 중앙값만을 확인한다.
            for(int lr=0;lr<n;lr++){
                for(int lc=0;lc<n;lc++){
                    if(sheet[row+lr][col+lc]==0) return false;
                }
            }
            return true;
        }
    
        public static void main(String[] args) throws IOException {
            //Setting();
            //boolean res = solution(new int[][]{{0, 0, 0}, {1, 0, 0}, {0, 1, 1}}, new int[][]{{1, 1, 1}, {1, 1, 0}, {1, 0, 1}});
            //boolean res = solution(new int[][]{{0, 0, 0}, {1, 0, 0}, {0, 1, 1}}, new int[][]{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}});
            boolean res = solution(new int[][]{{1}}, new int[][]{{0}});
            System.out.println(res);
    
        }
    
    }

    実行中にエラーが発生しました。


    念のため.
            // 첫 번째 모양을 세팅
            for(int r=0;r<lock.length;r++){
                for(int c =0;c<lock[0].length;c++){
                    gkey[0][r][c]= key[r][c];
                }
            }
    既存の上の部分を以下のように変更し、正解を得ました.
    // 첫 번째 모양을 세팅
            for(int r=0;r<m;r++){
                for(int c =0;c<m;c++){
                    gkey[0][r][c]= key[r][c];
                }
            }