第24講 特殊種法で魔方陣を超高速に自動生成する
第10話 直交させるためのヒント
5 | 3 | 2 | 1 | 4 |
3 | 4 | 1 | 5 | 2 |
1 | 2 | 3 | 4 | 5 |
4 | 1 | 5 | 2 | 3 |
2 | 5 | 4 | 3 | 1 |
1 | 5 | 4 | 2 | 3 |
3 | 4 | 1 | 5 | 2 |
5 | 3 | 2 | 4 | 1 |
2 | 1 | 5 | 3 | 4 |
4 | 2 | 3 | 1 | 5 |
の直交性を確認するには、碁盤
1 | 2 | 3 | 4 | 5 | |
1 | ○ | ○ | ○ | ○ | ○ |
2 | ○ | ○ | ○ | ○ | ○ |
3 | ○ | ○ | ○ | ○ | ○ |
4 | ○ | ○ | ○ | ○ | ○ |
5 | ○ | ○ | ○ | ○ | ○ |
を用意して、そこに碁石を置いていきます。
5 | 3 | 2 | 1 | 4 |
3 | 4 | 1 | 5 | 2 |
1 | 2 | 3 | 4 | 5 |
4 | 1 | 5 | 2 | 3 |
2 | 5 | 4 | 3 | 1 |
1 | 5 | 4 | 2 | 3 |
3 | 4 | 1 | 5 | 2 |
5 | 3 | 2 | 4 | 1 |
2 | 1 | 5 | 3 | 4 |
4 | 2 | 3 | 1 | 5 |
例えば、最初に組み合わせ(5,1)
(以下、色の対応に注意して読んでください。5は
5 |
対応しますし、1は
1 |
に対応しています。)
に碁石を置くと、
1 | 2 | 3 | 4 | 5 | |
1 | ○ | ○ | ○ | ○ | ○ |
2 | ○ | ○ | ○ | ○ | ○ |
3 | ○ | ○ | ○ | ○ | ○ |
4 | ○ | ○ | ○ | ○ | ○ |
5 | ○ | ○ | ○ | ○ | ○ |
となります。そして、次ぎに
5 | 3 | 2 | 1 | 4 |
3 | 4 | 1 | 5 | 2 |
1 | 2 | 3 | 4 | 5 |
4 | 1 | 5 | 2 | 3 |
2 | 5 | 4 | 3 | 1 |
1 | 5 | 4 | 2 | 3 |
3 | 4 | 1 | 5 | 2 |
5 | 3 | 2 | 4 | 1 |
2 | 1 | 5 | 3 | 4 |
4 | 2 | 3 | 1 | 5 |
の組み合わせ(3,5)に碁石を置いて、
1 | 2 | 3 | 4 | 5 | |
1 | ○ | ○ | ○ | ○ | ○ |
2 | ○ | ○ | ○ | ○ | ○ |
3 | ○ | ○ | ○ | ○ | ○ |
4 | ○ | ○ | ○ | ○ | ○ |
5 | ○ | ○ | ○ | ○ | ○ |
以下同様に(1,2),(4,3),(3,3)と置くと
1 | 2 | 3 | 4 | 5 | |
1 | ○ | ○ | ○ | ○ | ○ |
2 | ○ | ○ | ○ | ○ | ○ |
3 | ○ | ○ | ○ | ○ | ○ |
4 | ○ | ○ | ○ | ○ | ○ |
5 | ○ | ○ | ○ | ○ | ○ |
となっていきます。このように置いていって、
1 | 2 | 3 | 4 | 5 | |
1 | ○ | ○ | ○ | ○ | ○ |
2 | ○ | ○ | ○ | ○ | ○ |
3 | ○ | ○ | ○ | ○ | ○ |
4 | ○ | ○ | ○ | ○ | ○ |
5 | ○ | ○ | ○ | ○ | ○ |
と1つずつ置ければ、直交ですし、
同じところ2つ以上碁石が重なれば直交しません。
尚、再帰的関数が1つ手前の再帰的関数に帰るときには、
置いた碁石を取り去ることを忘れないで下さい。
もちろん、すでに置いてあった(=1つ以上手前の再帰的関数が碁石を置いた)
場合には、取り去ってはいけませんね。
では、以上を参考にして魔方陣特殊種法による自動生成ソフト完成させましょう。
なんと、5次魔方陣57600個が3.387秒で出来ました。
1個あたり0.0000588020833333333秒という信じられない高速化に
成功しています。
尚、碁盤に対応する配列を付け加えるため、
#include<iostream>
using namespace std;
int f1(int g,int m1[10][10],int m2[10][10],int a[10][10],int n,int* p,int* q,int cn);
int f2(int g,int m1[10][10],int m2[10][10],int a[10][10],int n,int* p,int* q,int cn);
void h(int m1[10][10],int m2[10][10],int n);
void zh(int n,int *p,int *q);
void sy(int m1[10][10],int n);
void sy1(int m2[10][10],int a[10][10],int n);
void main(){
int m1[10][10],m2[10][10],a[10][10],n,t=0;
・・・
・・・
cout<<n<<"次魔方陣種が"<<endl<<f1(0,m1,m2,a,n,p,q,0)<<"個できました。"<<endl;;
cout<<"プロジェクト終了"<<endl;
}
void zh(int n,int *p,int *q){
・・・
・・・
}
int f1(int g,int m1[10][10],int m2[10][10],int a[10][10],int n,int* p,int* q,int cn){
・・・
・・・
if(g+1<n*n){
cn=f1(g+1,m1,m2,a,n,p,q,cn);
}
else{
cn=f2(0,m1,m2,a,n,p,q,cn);
}
tobi:;
}
return(cn);
}
int f2(int g,int m1[10][10],int m2[10][10],int a[10][10],int n,int* p,int* q,int cn){
・・・
・・・
if(g+1<n*n){
cn=f2(g+1,m1,m2,a,n,p,q,cn);
//if(cn==100)return(cn);
}
else{
h(m1,m2,n);
cout<<endl<<endl;
//if(cn==100)return(cn);
cn++;
}
tobi:;
}
return(cn);
}
void h(int m1[10][10],int m2[10][10],int n){
・・・
・・・
}
と変更しておきましょう。