朝日新聞2006年7月28日のパズル横丁問題

問題

以下のように3x3の正方形がある。この中には1x1の大きさの正方形が9個,2x2の大きさの正方形が4個,3x3の大きさの正方形が1個あると見なすことが出来る。

このとき正方形を構成する24本の辺の何本かを取り除き異なる大きさの正方形が2個になるようにしたい。最小何本取り除けば良いか?

その時,正方形以外の図形はいくつあっても構わない。

2x2の4個の正方形と3x3の1個の正方形は以下のようになる。

解答への道(ヒント)

最初14個の正方形から2個を選択して組み合わせれば良いと思ったけど,それではダメ。

プログラムを作ってから間違いに気づいた。

結局,24枚の辺のあるなしを全て虱潰すことにする。24ビットのループを考え,ビットがONの所が辺があり,ビットがOFFの所が辺が無いものとする。

虱潰す方法は大体以下の通り。

for( int i=0; i<= 0xFFFFFF; i++) { // 全ての辺の組み合わせを調べる
  if( 異なる大きさの正方形が2個) {
    if( 今までより辺の数(ビット数)が多い) {
      iを記録
    }
  }
}

24ビットの数字から正方形を取り出すために,以下のように24本の辺に番号を振る。

そして14個の正方形を以下のように定義する。

  // +−0−+−1−+−2−+
  // |   |   |   | 
  // 12 A 13 B 14 C 15
  // |   |   |   | 
  // +−3−+−4−+−5−+ 
  // |   |   |   | 
  // 16 D 17 E 18 F 19 
  // |   |   |   | 
  // +−6−+−7−+−8−+ 
  // |   |   |   | 
  // 20 G 21 H 22 I 23
  // |   |   |   |
  // +−9−+−10−+−11−+
  ulong         rect[14] = {    // 正方形の定義
    /*A*/         bit0|bit3|bit12|bit13,
    /*B*/         bit1|bit4|bit13|bit14,
    /*C*/         bit2|bit5|bit14|bit15,
    /*D*/         bit3|bit6|bit16|bit17,
    /*E*/         bit4|bit7|bit17|bit18,
    /*F*/         bit5|bit8|bit18|bit19,
    /*G*/         bit6|bit9|bit20|bit21,
    /*H*/         bit7|bit10|bit21|bit22,
    /*I*/         bit8|bit11|bit22|bit23,
    /*ABDE*/      bit0|bit1|bit6|bit7|bit12|bit16|bit14|bit18,
    /*BCEF*/      bit1|bit2|bit7|bit8|bit13|bit17|bit15|bit19,
    /*DEGH*/      bit3|bit4|bit9|bit10|bit16|bit20|bit18|bit22,
    /*EFHI*/      bit4|bit5|bit10|bit11|bit17|bit21|bit19|bit23,
    /*ABCDEFGHI*/ bit0|bit1|bit2|bit9|bit10|bit11|bit12|bit16|bit20|bit15|bit19|bit23,
  };
  int           rect_size[14] = { // 1辺を1としたときの正方形の大きさ
    1,1,1,1,1,1,1,1,1,4,4,4,4,9
  };

 こうすると,以下のように正方形を検出できるので,残った正方形の数が判る。

  for( int i=0; i<= 0xFFFFFF; i++) { // 全ての辺の組み合わせを調べる
    for( int j=0; j< 14; j++) { // 14個の正方形を全て調べる
      if( (rect[j]&i) == rect[j]) { // 正方形が見つかった
        ………
      }
    }
    if( 見つかった正方形が2個で大きさが異なれば) {
      if( bitcount(i) が今までより多い) {
        iを記録。
      }
    }
  }

異なる大きさの正方形が2個残る場合を全て記録して最後に出力する。

答えは2件出力されました。但し,切り方の問題だけなので実質1件。

 

椅子がボロボロ。安い椅子はダメだなーと思うけど,座り心地が良いからなかなかリプレースできない。

解速度

Pentium Xeon2.4GHz で約1.2秒