課題4で完成させたプログラムの高速化を試みる。 元の関数等は消さずに残しておき、速度比較ができるようにする。 速度比較は盤面のサイズ n の変化に対し,全解探索に要する時間がど う変化するか調べること。
以下にはさまざまな高速化手法を示すが、 部分解の内容のコピーを避ける形で高速化を行うことを必須とする。 すべての高速化手法を試す必要はない。余力がある場合、他の実験履修者の 速度を上回りたい場合などに参考にすること。
[0, 1, 2, 3] のように初期化しておく.
	  1行目に関して各桁への拡張を試みる場合は:
	  [0, 1, 2, 3], [1, 0, 2, 3], [2, 1, 0, 3], [3, 1, 2, 0] 
	  のように,他の行の桁と入れ替える.次に,[1, 0, 2, 3] 
	  の2行目に関して拡張する場合は,
	  [1, 0, 2, 3], [1, 2, 0, 3], [1, 3, 2, 0]
	  のように残りの行との間でのみ入れ替えを行えば,自動的に3通りのみ拡張を
	  試みることができる.
	  左上から右下に 右上から左下に 見た場合 見た場合 3 2 1 0 0 1 2 3 4 3 2 1 1 2 3 4 5 4 3 2 2 3 4 5 6 5 4 3 3 4 5 6
bm から,
	  最下位の1ビットを取り出すには -bm & bm  とすればよい.
	  例えば,bm =
	   (00000000000000000000000001101000)2 なら,-bm =
	   (11111111111111111111111110011000)2 となるので
	   (つまり,bm + (-bm) のすべてのビットは 0), -bm & bm  = 
	   (00000000000000000000000000001000)2 となる.   
	  
traverse(部分解 *a) {
  if(*aは解) return;
  forall (拡張方向 i) {
    if( *a を i方向に拡張可能 ) {
       *a そのもの(内容)を変更し,i方向に一段階拡張;
       traverse(a);
       *a への変更(i方向に一段階拡張)を元に戻す; 
    }
  }
}
      +---+---+---+---+---+ | | | Q | | | +---+---+---+---+---+ | | | | | Q | <= いまここに置いた +---+---+---+---+---+ | | | | | | +---+---+---+---+---+ | | | | | | +---+---+---+---+---+ | | | | | | +---+---+---+---+---+と2行目に駒を置いた時点で,これを左回転した
+---+---+---+---+---+ | | Q | | | | +---+---+---+---+---+ | | | | | | +---+---+---+---+---+ | Q | | | | | +---+---+---+---+---+ | | | | | | +---+---+---+---+---+ | | | | | | +---+---+---+---+---+を考えると,この先,解まで拡張できたとしても,この先の置き方によらず, 左回転した解のほうが小さいことがわかるので,2行目をこのように置いた先の 探索を打ち切ればよい. (なお,この場合は,左右反転した解も小さいのでそれで打ち切ることも可能)
int f(int k, int *a){
  if(k == 0)
    {
      return *a;
    }
  else
    {
      int i, s = 0;
      for(i=0;i<k;i++){
        (*a) += i;
        s += f(k-1, a);
        (*a) -= i;
      }
      return s;
    }
}
という再帰呼出しを用いた計算は,明示的なスタックを用いることで
int f2(int k, int *a){
  int st[10000];
  int s = 0;
  int k0 = k;
 Ls:
  if(k == 0)
    {
      s += *a;
    }
  else
    {
      int i;
      for(i=0;i<k;i++){
        (*a) += i;
        st[k--] = i;
        goto Ls;
      Lc:
        i = st[++k];
        (*a) -= i;
      }
    }
  if(k == k0) return s;
  goto Lc;
}
のように変更することができる.