第21講 末項確定法
第2話 f1解答例と簡単な解説

void f1(int g){
  if(s==100)return;
  int i,j,h,wa,kk,kkk,m,sa;
  if(g==n-1){
    wa=0;
    for(j=0;j<n-1;j++){
      wa+=a1[j][j];
    }
    sa=n*(n-1)/2-wa;
    if(sa<0 || sa>n-1)return;
    if(cn1[sa]>n-1)return;
    a1[y[g]][x[g]]=sa;
    cn1[sa]++;
    f1(g+1);
    cn1[sa]--;
    return;
  }
  if(y[g]==n-1 && x[g]==0){
    wa=0;
    for(j=0;j<n-1;j++){
      wa+=a1[j][n-1-j];
    }
    sa=n*(n-1)/2-wa;
    if(sa<0 || sa>n-1)return;
    if(cn1[sa]>n-1)return;
    a1[y[g]][x[g]]=sa;
    cn1[sa]++;
    f1(g+1);
    cn1[sa]--;
    return;
  }
  if(y[g]==0 && x[g]==n-2){
    wa=0;
    for(j=0;j<n-2;j++){
      wa+=a1[0][j];
    }
    wa+=a1[0][n-1];
    sa=n*(n-1)/2-wa;
    if(sa<0 || sa>n-1)return;
    if(cn1[sa]>n-1)return;
    a1[y[g]][x[g]]=sa;
    cn1[sa]++;
    f1(g+1);
    cn1[sa]--;
    return;
  }
  if(y[g]==n-2 && x[g]==0){
    wa=0;
    for(j=0;j<n-2;j++){
      wa+=a1[j][0];
    }
    wa+=a1[n-1][0];
    sa=n*(n-1)/2-wa;
    if(sa<0 || sa>n-1)return;
    if(cn1[sa]>n-1)return;
    a1[y[g]][x[g]]=sa;
    cn1[sa]++;
    f1(g+1);
    cn1[sa]--;
    return;
  }
  if(y[g]>0 && y[g]<n-1 && x[g]==n-1){
    wa=0;
    for(j=0;j<n-1;j++){
      wa+=a1[y[g]][j];
    }
    sa=n*(n-1)/2-wa;
    if(sa<0 || sa>n-1)return;
    if(cn1[sa]>n-1)return;
    a1[y[g]][x[g]]=sa;
    cn1[sa]++;
    f1(g+1);
    cn1[sa]--;
    return;
  }
  if(x[g]>0 && x[g]<n-1 && y[g]==n-1){
    wa=0;
    for(j=0;j<n-1;j++){
      wa+=a1[j][x[g]];
    }
    sa=n*(n-1)/2-wa;
    if(sa<0 || sa>n-1)return;
    if(cn1[sa]>n-1)return;
    a1[y[g]][x[g]]=sa;
    cn1[sa]++;
    if(g<n*n-1){
      f1(g+1);
      if(s==100)return;
    }
    else{
      f2(0);
      if(s==100)return;
    }
    cn1[sa]--;
    return;
  }
  kk=rand()%n;
  m=n/2;
  for(i=0;i<n;i++){
    kkk=(kk+i)%n;
    a1[y[g]][x[g]]=kkk;
    h=1;
    cn1[kkk]++;
    if(cn1[kkk]>n)h=0;
    if(h==1)f1(g+1);
    cn1[kkk]--;
  }
}



(コピーペースト用



void f1(int g){
if(s==100)return;
int i,j,h,wa,kk,kkk,m,sa;
if(g==n-1){
wa=0;
for(j=0;j<n-1;j++){
wa+=a1[j][j];
}
sa=n*(n-1)/2-wa;
if(sa<0 || sa>n-1)return;
if(cn1[sa]>n-1)return;
a1[y[g]][x[g]]=sa;
cn1[sa]++;
f1(g+1);
cn1[sa]--;
return;
}
if(y[g]==n-1 && x[g]==0){
wa=0;
for(j=0;j<n-1;j++){
wa+=a1[j][n-1-j];
}
sa=n*(n-1)/2-wa;
if(sa<0 || sa>n-1)return;
if(cn1[sa]>n-1)return;
a1[y[g]][x[g]]=sa;
cn1[sa]++;
f1(g+1);
cn1[sa]--;
return;
}
if(y[g]==0 && x[g]==n-2){
wa=0;
for(j=0;j<n-2;j++){
wa+=a1[0][j];
}
wa+=a1[0][n-1];
sa=n*(n-1)/2-wa;
if(sa<0 || sa>n-1)return;
if(cn1[sa]>n-1)return;
a1[y[g]][x[g]]=sa;
cn1[sa]++;
f1(g+1);
cn1[sa]--;
return;
}
if(y[g]==n-2 && x[g]==0){
wa=0;
for(j=0;j<n-2;j++){
wa+=a1[j][0];
}
wa+=a1[n-1][0];
sa=n*(n-1)/2-wa;
if(sa<0 || sa>n-1)return;
if(cn1[sa]>n-1)return;
a1[y[g]][x[g]]=sa;
cn1[sa]++;
f1(g+1);
cn1[sa]--;
return;
}
if(y[g]>0 && y[g]<n-1 && x[g]==n-1){
wa=0;
for(j=0;j<n-1;j++){
wa+=a1[y[g]][j];
}
sa=n*(n-1)/2-wa;
if(sa<0 || sa>n-1)return;
if(cn1[sa]>n-1)return;
a1[y[g]][x[g]]=sa;
cn1[sa]++;
f1(g+1);
cn1[sa]--;
return;
}
if(x[g]>0 && x[g]<n-1 && y[g]==n-1){
wa=0;
for(j=0;j<n-1;j++){
wa+=a1[j][x[g]];
}
sa=n*(n-1)/2-wa;
if(sa<0 || sa>n-1)return;
if(cn1[sa]>n-1)return;
a1[y[g]][x[g]]=sa;
cn1[sa]++;
if(g<n*n-1){
f1(g+1);
if(s==100)return;
}
else{
f2(0);
if(s==100)return;
}
cn1[sa]--;
return;
}
kk=rand()%n;
m=n/2;
for(i=0;i<n;i++){
kkk=(kk+i)%n;
a1[y[g]][x[g]]=kkk;
h=1;
cn1[kkk]++;
if(cn1[kkk]>n)h=0;
if(h==1)f1(g+1);
cn1[kkk]--;
}

}





  if(g==n-1){
    wa=0;
    for(j=0;j<n-1;j++){
      wa+=a1[j][j];
    }
    sa=n*(n-1)/2-wa;
    if(sa<0 || sa>n-1)return;
    if(cn1[sa]>n-1)return;
    a1[y[g]][x[g]]=sa;
    cn1[sa]++;
    f1(g+1);
    cn1[sa]--;
    return;
  }
などの基本構造は同じです。

0 1 2 3 4 5 6 7 8 9
0 0 20 21 22 23 24 25 26 27 10
1 28 1 36 37 38 39 40 41 11 42
2 29 43 2 50 51 52 53 12 54 55
3 30 44 56 3 62 63 13 64 65 66
4 31 45 57 67 4 14 72 73 74 75
5 32 46 58 68 15 5 80 81 82 83
6 33 47 59 16 76 84 6 88 89 90
7 34 48 17 69 77 85 91 7 94 95
8 35 18 60 70 78 86 92 96 8 98
9 19 49 61 71 79 87 93 97 99 9

それは、基本的には水色以外の色のセルに来たときは、上の世界(g+1)の世界に上がるか、
下の世界(g−1)に戻るしかないのです。
ここではfor文で探索しなくていいわけです。
基本構造は同じですが、
各if文が少しずつ異なっている理由は、
色によって対角線を合計したり、行や列を合計したりしなければならないからです。
例えば、

09


のときには対角線

0 1 2 3 4 5 6 7 8 9
0 0 20 21 22 23 24 25 26 27 10
1 28 1 36 37 38 39 40 41 11 42
2 29 43 2 50 51 52 53 12 54 55
3 30 44 56 3 62 63 13 64 65 66
4 31 45 57 67 4 14 72 73 74 75
5 32 46 58 68 15 5 80 81 82 83
6 33 47 59 16 76 84 6 88 89 90
7 34 48 17 69 77 85 91 7 94 95
8 35 18 60 70 78 86 92 96 8 98
9 19 49 61 71 79 87 93 97 99

を合計しなければなりません。
注意しなけれいけないのは、

27


35


のセルのときです。




  if(y[g]==0 && x[g]==n-2){
    wa=0;
    for(j=0;j<n-2;j++){
      wa+=a1[0][j];
    }
    wa+=a1[0][n-1];
    sa=n*(n-1)/2-wa;
    if(sa<0 || sa>n-1)return;
    if(cn1[sa]>n-1)return;
    a1[y[g]][x[g]]=sa;
    cn1[sa]++;
    f1(g+1);
    cn1[sa]--;
    return;
  }
  if(y[g]==n-2 && x[g]==0){
    wa=0;
    for(j=0;j<n-2;j++){
      wa+=a1[j][0];
    }
    wa+=a1[n-1][0];
    sa=n*(n-1)/2-wa;
    if(sa<0 || sa>n-1)return;
    if(cn1[sa]>n-1)return;
    a1[y[g]][x[g]]=sa;
    cn1[sa]++;
    f1(g+1);
    cn1[sa]--;
    return;
  }
他の部分と合計の仕方が違うのは、

0 1 2 3 4 5 6 7 8 9
0 0 20 21 22 23 24 25 26 27 10
1 28 1 36 37 38 39 40 41 11 42
2 29 43 2 50 51 52 53 12 54 55
3 30 44 56 3 62 63 13 64 65 66
4 31 45 57 67 4 14 72 73 74 75
5 32 46 58 68 15 5 80 81 82 83
6 33 47 59 16 76 84 6 88 89 90
7 34 48 17 69 77 85 91 7 94 95
8 35 18 60 70 78 86 92 96 8 98
9 19 49 61 71 79 87 93 97 99 9
0 1 2 3 4 5 6 7 8 9
0 0 20 21 22 23 24 25 26 27 10
1 28 1 36 37 38 39 40 41 11 42
2 29 43 2 50 51 52 53 12 54 55
3 30 44 56 3 62 63 13 64 65 66
4 31 45 57 67 4 14 72 73 74 75
5 32 46 58 68 15 5 80 81 82 83
6 33 47 59 16 76 84 6 88 89 90
7 34 48 17 69 77 85 91 7 94 95
8 35 18 60 70 78 86 92 96 8 98
9 19 49 61 71 79 87 93 97 99 9


19

の存在です。
ここはすれに数字が埋まっています。
ですから

35

の前までと

19







を加えなければならないです。

















さて、最後だけ
  if(x[g]>0 && x[g]<n-1 && y[g]==n-1){
    wa=0;
    for(j=0;j<n-1;j++){
      wa+=a1[j][x[g]];
    }
    sa=n*(n-1)/2-wa;
    if(sa<0 || sa>n-1)return;
    if(cn1[sa]>n-1)return;
    a1[y[g]][x[g]]=sa;
    cn1[sa]++;
    if(g<n*n-1){
      f1(g+1);
      if(s==100)return;
    }
    else{
      f2(0);
      if(s==100)return;
    }
    cn1[sa]--;
    return;
  }
他とはかなり違っています。

0 1 2 3 4 5 6 7 8 9
0 0 20 21 22 23 24 25 26 27 10
1 28 1 36 37 38 39 40 41 11 42
2 29 43 2 50 51 52 53 12 54 55
3 30 44 56 3 62 63 13 64 65 66
4 31 45 57 67 4 14 72 73 74 75
5 32 46 58 68 15 5 80 81 82 83
6 33 47 59 16 76 84 6 88 89 90
7 34 48 17 69 77 85 91 7 94 95
8 35 18 60 70 78 86 92 96 8 98
9 19 49 61 71 79 87 93 97 99 9

理由は、茶色セルの中に

0 1 2 3 4 5 6 7 8 9
0 0 20 21 22 23 24 25 26 27 10
1 28 1 36 37 38 39 40 41 11 42
2 29 43 2 50 51 52 53 12 54 55
3 30 44 56 3 62 63 13 64 65 66
4 31 45 57 67 4 14 72 73 74 75
5 32 46 58 68 15 5 80 81 82 83
6 33 47 59 16 76 84 6 88 89 90
7 34 48 17 69 77 85 91 7 94 95
8 35 18 60 70 78 86 92 96 8 98
9 19 49 61 71 79 87 93 97 99 9

最後のセル

99

が存在するからです。
ここまで来たら、一般種の1個目は完成で、
2個目の種の製作関数f2に進まなければならないので、
ここだけ少し変わっているのです。





では皆さん、f1を参考にしてf2を考えましょう。
結構難しいですよ。






第21講第1話へ 第21講第3話へ


VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座