/******************************************************************************
Cマガジン2005年2月号電脳クラブ出題(アンカーパチンコ)
*****************************************************************************/*
#include <stdio.h>
#include <stdlib.h>
#define N0 0 /* 基準の数 /*
#define N1 1 /* 最小単位の数 /*
#define N2 2 /* N1 + N1 /*
#define NON -1 /* 最下段のアンカーのため、次がない状態 /*
#define R_ANC 0 /* アンカーが右に倒れている状態 /*
#define L_ANC 1 /* アンカーが左に倒れている状態 /*
typedef struct {
int r; /* アンカーが右に倒れている場合の進み先 /*
int l; /* アンカーが左に倒れている場合の進み先 /*
} ANCHOR; /* アンカー間の移動の定義構造体 /*
#ifdef FIG1 /* Fig.1用定義 /*
#define YOKO 3 /* アンカーパチンコの横方向の大きさ /*
#define TATE 3 /* アンカーパチンコの縦方向の大きさ /*
#else /* Fig.3用定義 /*
#define YOKO 4 /* アンカーパチンコの横方向の大きさ /*
#define TATE 5 /* アンカーパチンコの縦方向の大きさ /*
#endif
ANCHOR *anchor; /* アンカー間の移動の定義 /*
int nAnchor; /* アンカーの数 /*
int nPattern; /* パチンコ台のパターンの数 /*
int *seni; /* パターン間の遷移 /*
int *min; /* そのパターンに到達するまでの最小手順数 /*
int *tejun; /* そこまでの手順 /*
int *seikai; /* 正解手順 /*
int *bit2; /* ビット計算用(1,2,4,8,...) /*
/******************************************************************************
機能:再帰呼び出しで解を探査する
引数:
(1) m1 : パターン番号
(2) n : これまでに落とした玉の数
戻り値:なし
*****************************************************************************/*
void tansa(int patNo , int n)
{
int i; /* ループの制御変数 /*
int nextPatNo; /* 次のパターン番号 /*
if(n >= min[patNo]) return; /* 過去にこのパターンにたどり着いた最小玉数 /*
min[patNo] = n;
if(patNo == (nPattern - N1)) { /* 最終パターンにたどり着いたか /*
for(i = N0 ; i < n ; i++) seikai[i] = tejun[i]; /* 手順を記録 /*
return;
}
for(i = N0 ; i < YOKO ; i++) { /* A〜CorDに玉を落とす /*
tejun[n] = i;
nextPatNo = seni[patNo * YOKO + i]; /* 次にパターンを求める /*
tansa(nextPatNo , n + N1); /* 次へ /*
}
}
/******************************************************************************
機能:パターン間の遷移を作る
引数:
(1) stat : 各アンカーの状態
(2) patNo : パチンコ台のパターン番号
戻り値:なし
*****************************************************************************/*
void setSeni(int stat[] , int patNo)
{
int nextPatNo; /* 玉を1個落とした後のパターン番号 /*
int i , j; /* ループの制御変数 /*
int t1; /* 一時変数 /*
int *nextStat; /* 玉を1個落とした後のアンカーの状態 /*
nextStat = (int *)malloc(sizeof(int) * nAnchor);
if(nextStat == NULL) {
fprintf(stderr , "malloc error at %d\n" , __LINE__ - 2);
return;
}
for(i = N0 ; i < YOKO ; i++) { /* 玉をA〜CorDに落とす /*
for(j = N0 ; j < nAnchor ; j++) nextStat[j] = stat[j];
t1 = i;
while(t1 != NON) {
if(nextStat[t1] == R_ANC) { /* アンカー=右の場合 /*
nextStat[t1] = L_ANC; /* 状態を左にする /*
t1 = anchor[t1].r;
}
else { /* アンカー=左の場合 /*
nextStat[t1] = R_ANC; /* 状態を右にする /*
t1 = anchor[t1].l;
}
}
nextPatNo = N0; /* 次のパターン番号を求める /*
for(j = N0 ; j < nAnchor ; j++) {
nextPatNo += nextStat[j] * bit2[j];
}
seni[patNo * YOKO + i] = nextPatNo;
}
free(nextStat);
}
/******************************************************************************
機能:パチンコ台の全パターンを生成する
引数:
(1) stat : 各アンカーの状態
(2) n : これまでに状態を設定したアンカーの数
(3) patNo : パチンコ台のパターン番号
戻り値:なし
*****************************************************************************/*
void makePattern(int stat[] , int n , int patNo)
{
int i; /* ループの制御変数 /*
if(n == nAnchor) { /* 全てのアンカーに状態をセットした /*
setSeni(stat , patNo);
return;
}
for(i = R_ANC ; i <= L_ANC ; i++) { /* アンカーに右、左をセット /*
stat[n] = i;
makePattern(stat , n + N1 , patNo + i * bit2[n]); /* 次へ /*
}
}
/******************************************************************************
機能:メイン
引数:なし
戻り値:EXIT_SUCCESS
*****************************************************************************/*
int main(void)
{
int i; /* ループの制御変数 /*
int *stat; /* 各アンカーの状態 /*
int x , y; /* ループの制御変数 /*
int n = N0;
nAnchor = YOKO * TATE - TATE / N2; /* アンカーの個数を求める /*
stat = (int *)malloc(sizeof(int) * nAnchor);
if(stat == NULL) {
fprintf(stderr , "malloc error at %d\n" , __LINE__ - 2);
}
bit2 = (int *)malloc(sizeof(int) * nAnchor);
if(bit2 == NULL) {
free(stat);
fprintf(stderr , "malloc error at %d\n" , __LINE__ - 3);
}
bit2[N0] = N1;
for(i = N1 ; i < nAnchor ; i++) bit2[i] = bit2[i - N1] * N2;
nPattern = bit2[nAnchor - N1] * N2;
seni = (int *)malloc(sizeof(int) * nPattern * YOKO);
if(seni == NULL) {
free(stat);
free(bit2);
fprintf(stderr , "malloc error at %d\n" , __LINE__ - 4);
}
min = (int *)malloc(sizeof(int) * nPattern);
if(min == NULL) {
free(stat);
free(bit2);
free(seni);
fprintf(stderr , "malloc error at %d\n" , __LINE__ - 5);
}
tejun = (int *)malloc(sizeof(int) * nPattern);
if(tejun == NULL) {
free(stat);
free(bit2);
free(seni);
free(min);
fprintf(stderr , "malloc error at %d\n" , __LINE__ - 6);
}
seikai = (int *)malloc(sizeof(int) * nPattern);
if(seikai == NULL) {
free(stat);
free(bit2);
free(seni);
free(min);
free(tejun);
fprintf(stderr , "malloc error at %d\n" , __LINE__ - 7);
}
for(i = N0 ; i < nPattern ; i++) min[i] = nPattern;
anchor = (ANCHOR *)malloc(sizeof(ANCHOR) * nAnchor);
if(anchor == NULL) {
free(stat);
free(bit2);
free(seni);
free(min);
free(tejun);
free(seikai);
fprintf(stderr , "malloc error at %d\n" , __LINE__ - 8);
}
for(y = N0 ; y < TATE - N1 ; y += N2) {
for(x = N0 ; x < YOKO ; x++) {
if(x == N0) anchor[n].r = n + YOKO * N2 - N1;
else anchor[n].r = n + YOKO - N1;
if(x == YOKO - N1 ) anchor[n].l = n + YOKO * N2 - N1;
else anchor[n].l = n + YOKO;
n++;
}
for(x = N0 ; x < YOKO - N1 ; x++) {
anchor[n].r = n + YOKO - N1;
anchor[n].l = n + YOKO;
n++;
}
}
for(x = N0 ; x < YOKO ; x++) {
anchor[n].r = anchor[n].l = NON;
n++;
}
makePattern(stat , N0 , N0); /* パターン、遷移を作る /*
free(bit2);
free(stat);
tansa(N0 , N0); /* 解を探査する /*
for(i = N0 ; i < min[nPattern - N1] ; i++) printf("%c " , 'A' + seikai[i]);
printf("\n"); /* 解答表示 /*
free(anchor);
free(seikai);
free(tejun);
free(min);
free(seni);
return(EXIT_SUCCESS);
}
|
第168回(3月)ダブル・スクエア
|
|
/****************************************************************************
Cマガジン2004年12月号電脳クラブ出題(ダブル・スクエア)
***************************************************************************/*
#include <stdio.h>
#include <stdlib.h>
#define OFF 0 /* オフ /*
#define ON 1 /* オン /*
#define OK 0 /* OK /*
#define NG 1 /* NG /*
#define DOWN 0 /* Z座標下側の座標 /*
#define UP 1 /* Z座標上側の座標 /*
#define N0 0 /* 基準値 /*
#define N1 1 /* 最小の単位の数 /*
#define NON -1 /* ピースを置いてない状態 /*
#define NP 8 /* ピースの数 /*
#define NH 8 /* ピースの方向の数 /*
#define NH4 4 /* NH / 2 /*
#define NX 8 /* 箱のX方向の大きさ /*
#define NY 8 /* 箱のY方向の大きさ /*
#define NZ 2 /* 箱のZ方向の大きさ /*
#define NPY 4 /* ピースのY方向の大きさの最大値 /*
#define MAXZ 22 /* ピースを構成する座標の数の最大値 /*
typedef struct {
int x; /* X座標 /*
int y; /* Y座標 /*
int z; /* Z座標 /*
} XYZ; /* 座標構造体 /*
static char *piece[NP][NPY] = { /* D:下にある、U:上にある、B:上下にある /*
"DDBU" , /* ピースAの定義 /*
"DDBU" ,
"DDD" ,
"" ,
" UUUU" , /* ピースBの定義 /*
" UUUU" ,
"DBUUU" ,
"DD" ,
"UU" , /* ピースCの定義 /*
"UBDD" ,
" DDD" ,
"" ,
" DDDD" , /* ピースDの定義 /*
"UUBBBD" ,
"UUBBBD" ,
"" ,
"UU" , /* ピースEの定義 /*
"UBDDD" ,
"UBDDD" ,
"UBDDD" ,
" UU" , /* ピースFの定義 /*
"DBBDD" ,
"DBBDD" ,
"" ,
"UU" , /* ピースGの定義 /*
"BBDD" ,
"BBDD" ,
"" ,
"UUU" , /* ピースHの定義 /*
"UUBDDD" ,
"UUBDDD" ,
"" };
XYZ pz[NP][NH][MAXZ]; /* ピースごと、方向ごとの座標 /*
int nPz[NP]; /* ピースごとの座標数 /*
int fUsed[NP]; /* ピース使用済みフラグ /*
int hako[NZ][NY][NX]; /* 箱の定義 /*
int count = N0; /* 正解 /*
/****************************************************************************
機 能:初期化
引 数:なし
戻り値:なし
***************************************************************************/*
void init(void)
{
int i , j , k , x , y , z; /* ループの制御変数 /*
int minx , miny; /* ピース下側のY座標最小値、及びX座標最小値 /*
char p1; /* 一時変数 /*
for(i = N0 ; i < NP ; i++) { /* ピースの座標を求める /*
nPz[i] = N0;
for(y = N0 ; y < NPY ; y++) {
for(x = N0 ; x < (int)strlen(piece[i][y]) ; x++) {
p1 = *(piece[i][y] + x);
if(p1 == 'D' || p1 == 'B') { /* 下側の処理 /*
pz[i][N0][nPz[i]].x = x;
pz[i][N0][nPz[i]].y = y;
pz[i][N0][nPz[i]].z = DOWN;
nPz[i]++;
}
if(p1 == 'U' || p1 == 'B') { /* 上側の処理 /*
pz[i][N0][nPz[i]].x = x;
pz[i][N0][nPz[i]].y = y;
pz[i][N0][nPz[i]].z = UP;
nPz[i]++;
}
}
}
}
for(i = N0 ; i < NP ; i++) { /* 方向ごとの座標を求める /*
for(j = N1 ; j < NH4 ; j++) { /* 90度、180度、270度回転 /*
for(k = N0 ; k < nPz[i] ; k++) {
pz[i][j][k].x = - pz[i][j - N1][k].y; /* 90度回転 /*
pz[i][j][k].y = pz[i][j - N1][k].x;
pz[i][j][k].z = pz[i][j - N1][k].z; /* Z座標はそのまま /*
}
}
for(k = N0 ; k < nPz[i] ; k++) { /* 上下反転 /*
pz[i][NH4][k].x = - pz[i][N0][k].x; /* X座標を反転 /*
pz[i][NH4][k].y = pz[i][N0][k].y;
pz[i][NH4][k].z = UP - pz[i][N0][k].z; /* 上下反転 /*
}
for(j = NH4 + N1 ; j < NH ; j++) { /* 90度、180度、270度回転 /*
for(k = N0 ; k < nPz[i] ; k++) {
pz[i][j][k].x = - pz[i][j - N1][k].y; /* 90度回転 /*
pz[i][j][k].y = pz[i][j - N1][k].x;
pz[i][j][k].z = pz[i][j - N1][k].z; /* Z座標はそのまま /*
}
}
}
for(i = N0 ; i < NP ; i++) {
for(j = N0 ; j < NH ; j++) {
miny = NY;
for(k = N0 ; k < nPz[i] ; k++) {
if(pz[i][j][k].z == UP) continue; /* 上側は無視する /*
if(pz[i][j][k].y < miny) { /* 基準座標を求める /*
minx = pz[i][j][k].x;
miny = pz[i][j][k].y;
}
else if(pz[i][j][k].y == miny && pz[i][j][k].x < minx) {
minx = pz[i][j][k].x;
}
}
for(k = N0 ; k < nPz[i] ; k++) {
pz[i][j][k].x -= minx; /* 基準座標からの相対座標とする /*
pz[i][j][k].y -= miny;
}
}
}
for(i = N0 ; i < NP ; i++) fUsed[i] = OFF; /* ピースを未使用にする /*
for(z = N0 ; z < NZ ; z++) { /* 箱にピースが置いてない状態にする /*
for(y = N0 ; y < NY ; y++) {
for(x = N0 ; x < NX ; x++) hako[z][y][x] = NON;
}
}
}
/****************************************************************************
機 能:箱にピースを置けるかどうかチェックし、置けるなら置く
引 数:
(1) x : 取り除くピースの基準X座標
(2) y : 取り除くピースの基準Y座標
(3) np : ピースの番号
(4) nh : ピースの方向
戻り値:OK:置ける(置いた)、NG:置けない
***************************************************************************/*
int check(int x , int y , int np , int nh)
{
int i; /* ループの制御変数 /*
int x2 , y2; /* 箱内の座標 /*
for(i = N0 ; i < nPz[np] ; i++) {
x2 = x + pz[np][nh][i].x; /* ピースを置く箱内のX座標 /*
if(x2 < N0 || x2 >= NX) return(NG); /* 範囲外 /*
y2 = y + pz[np][nh][i].y; /* ピースを置く箱内のY座標 /*
if(y2 < N0 || y2 >= NY) return(NG); /* 範囲外 /*
if(hako[pz[np][nh][i].z][y2][x2] != NON) return(NG); /* 既にある /*
}
for(i = N0 ; i < nPz[np] ; i++) { /* ピースを置く /*
x2 = x + pz[np][nh][i].x;
y2 = y + pz[np][nh][i].y;
hako[pz[np][nh][i].z][y2][x2] = np;
}
return(OK);
}
/****************************************************************************
機 能:箱からピースを取り除く
引 数:
(1) x : 取り除くピースの基準X座標
(2) y : 取り除くピースの基準Y座標
(3) np : ピースの番号
(4) nh : ピースの方向
戻り値:なし
***************************************************************************/*
void toru(int x , int y , int np , int nh)
{
int i; /* ループの制御変数 /*
int x2 , y2; /* 箱内の座標 /*
for(i = N0 ; i < nPz[np] ; i++) {
x2 = x + pz[np][nh][i].x;
y2 = y + pz[np][nh][i].y;
hako[pz[np][nh][i].z][y2][x2] = NON; /* ピースを取る /*
}
}
/****************************************************************************
機 能:結果例表示
引 数:なし
戻り値:なし
***************************************************************************/*
void disp(void)
{
int x , y , z; /* ループの制御変数 /*
printf("--------\n");
printf("箱の下側\n");
for(z = N0 ; z < NZ ; z++) {
for(y = N0 ; y < NY ; y++) {
for(x = N0 ; x < NX ; x++) {
printf("%c" , 'A' + hako[z][y][x]); /* ピースのID表示 /*
}
printf("\n");
}
if(z == N0) printf("箱の上側\n");
}
}
/****************************************************************************
機 能:ピースを1つ置く再帰呼び出し関数
引 数:
(1) x : ピースを置く基準X座標
(2) x : ピースを置く基準Y座標
(3) n : ここまでに置いたピースの数
戻り値:なし
***************************************************************************/*
void sub(int x , int y , int n)
{
int i , j; /* ループの制御変数 /*
if(n == NP) { /* ピースを全て置いたなら /*
disp(); /* 結果例表示 /*
count++; /* 正解数をカウントアップ /*
return;
}
while(hako[DOWN][y][x] != NON) { /* ピースを置いてない場所を探す /*
x++;
if(x == NX) {
x = N0;
y++;
}
}
for(i = N0 ; i < NP ; i++) { /* ピースを置く /*
if(fUsed[i] == ON) continue; /* 使用済みはスキップ /*
for(j = N0 ; j < NH ; j++) {
if(i == N0) { /* ピースAでは /*
if(j != N0) continue; /* 1方向のみ(鏡像排除) /*
}
if(check(x , y , i , j) == OK) {
fUsed[i] = ON; /* 使用済みにする /*
sub(x , y , n + N1); /* 次のピースへ /*
fUsed[i] = OFF; /* 未使用に戻す /*
toru(x , y , i , j); /* ピースを取り除く /*
}
}
}
}
/****************************************************************************
機 能:メイン
引 数:なし
戻り値:EXIT_SUCCESS
***************************************************************************/*
int main(void)
{
init(); /* 初期化 /*
sub(N0 , N0 , N0); /* ピースを置いていく /*
printf("%d通り\n" , count); /* 解答表示 /*
return(EXIT_SUCCESS);
}
|
第166回(1月)ロード・オブ・ザ・リンク
|
|
/******************************************************************************
Cマガジン2004年10月号電脳クラブ出題 ロード・オブ・ザ・リンク
*****************************************************************************/*
#include <stdio.h>
#include <stdlib.h>
#define OFF 0 /* オフ /*
#define ON 1 /* オン /*
#define N0 0 /* 基準値 /*
#define N1 1 /* 単位の数 /*
#define N26 26 /* アルファベットの個数 /*
#define NON -1 /* リンク線が来てない状態 /*
#define SUMI -2 /* チェック済み /*
typedef struct {
int sx; /* リンク線始点のX座標 /*
int sy; /* リンク線始点のY座標 /*
int sn; /* 始点の番号 /*
int ex; /* リンク線終点のX座標 /*
int ey; /* リンク線終点のY座標 /*
int en; /* 終点の番号 /*
int f1; /* OFF:始点未出現、ON:始点出現済み /*
} SE; /* リンク線始終点構造体 /*
SE se[N26];
int nSe = N0; /* リンク線の数-1 /*
int count = N0; /* 正解の個数 /*
int nx; /* 横幅 /*
int ny; /* 縦長 /*
int nxy; /* nx * ny /*
static char *teigi[] = { /* 問題の定義 /*
"...A...." ,
".B....C." ,
"........" ,
".C.....E" ,
"...D...." ,
"E.....B." ,
"..A....." ,
".......D" };
int *ban; /* 盤 /*
int *w1; /* ワーク /*
int fCheck; /* つながったかどうかのフラグ OFF:つながってない、ON:つながった /*
/******************************************************************************
機能:つながりを伸ばす
引数:
(1) x : X座標
(2) y : Y座標
(3) n : リンク線の番号
戻り値:なし
*****************************************************************************/*
void checkSub(int x , int y , int n)
{
int ynx;
ynx = y * nx;
if(x > N0) { /* 左方向に伸ばす /*
if(w1[ynx + x - N1] == se[n].en) { /* 終点にたどり着いたら /*
fCheck = ON; /* つながった /*
return;
}
if(w1[ynx + x - N1] == NON) { /* そこをリンク線が通ってなかったら /*
w1[ynx + x - N1] = SUMI; /* チェック済みにする /*
checkSub(x - N1 , y , n); /* 次へ /*
if(fCheck == ON) return;
}
}
if(y > N0) { /* 上方向に伸ばす /*
if(w1[ynx - nx + x] == se[n].en) { /* 終点にたどり着いたら /*
fCheck = ON; /* つながった /*
return;
}
if(w1[ynx - nx + x] == NON) { /* そこをリンク線が通ってなかったら /*
w1[ynx - nx + x] = SUMI; /* チェック済みにする /*
checkSub(x , y - N1 , n); /* 次へ /*
if(fCheck == ON) return;
}
}
if(x < nx - N1) { /* 右方向に伸ばす /*
if(w1[ynx + x + N1] == se[n].en) { /* 終点にたどり着いたら /*
fCheck = ON; /* つながった /*
return;
}
if(w1[ynx + x + N1] == NON) { /* そこをリンク線が通ってなかったら /*
w1[ynx + x + N1] = SUMI; /* チェック済みにする /*
checkSub(x + N1 , y , n); /* 次へ /*
if(fCheck == ON) return;
}
}
if(y < ny - N1) { /* 下方向に伸ばす /*
if(w1[ynx + nx + x] == se[n].en) { /* 終点にたどり着いたら /*
fCheck = ON; /* つながった /*
return;
}
if(w1[ynx + nx + x] == NON) { /* そこをリンク線が通ってなかったら /*
w1[ynx + nx + x] = SUMI; /* チェック済みにする /*
checkSub(x , y + N1 , n); /* 次へ /*
if(fCheck == ON) return;
}
}
}
/******************************************************************************
機能:n番目のリンク線が始点終点間でつながるかチェックする。
引数:
(1) n : チェックするリンク線の番号
戻り値:OFF:つながらない、ON:つながる
*****************************************************************************/*
int check(int n)
{
memcpy(w1 , ban , nxy * sizeof(int)); /* 盤をワークにコピーする /*
fCheck = OFF; /* フラグをつながらない状態にセットする /*
checkSub(se[n].sx , se[n].sy , n);
return(fCheck);
}
/******************************************************************************
機能:正解を表示する
引数:なし
戻り値:なし
*****************************************************************************/*
void disp(void)
{
int x , y; /* 座標 /*
int i; /* ループの制御変数 /*
int f1; /* 始終点だったかどうかのフラグ /*
int t1; /* 一時変数 /*
static char *alp[] = { /* アルファベット /*
"A","B","C","D","E","F","G","H","I","J","K","L","M",
"N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
count++; /* 正解の個数をカウントアップする /*
for(y = N0 ; y < ny ; y++) { /* ワークを初期化する /*
for(x = N0 ; x < nx ; x++) w1[y * nx + x] = NON;
}
for(y = N0 ; y < ny ; y++) { /* 各ポイントにリンク線の番号をセットする /*
for(x = N0 ; x < nx ; x++) {
t1 = y * nx + x;
for(i = 0 ; i <= nSe ; i++) {
if(ban[t1] >= se[i].sn && ban[t1] <= se[i].en) {
w1[t1] = i;
break;
}
}
}
}
printf("その%d\n" , count);
for(y = N0 ; y < ny ; y++) {
for(x = N0 ; x < nx ; x++) {
f1 = OFF;
for(i = N0 ; i <= nSe ; i++) { /* 始点かどうか /*
if(ban[y * nx + x] == se[i].sn) {
printf("%s" , alp[i]); /* 始点ならアルファベット表示 /*
f1 = ON;
break;
}
else if(ban[y * nx + x] == se[i].en) { /* 終点かどうか /*
printf("%s" , alp[i]); /* 終点ならアルファベット表示 /*
f1 = ON;
break;
}
}
if(f1 == OFF) printf("・"); /* 始終点以外 /*
if(x < nx - N1) { /* 横方向リンク線 /*
if(w1[y * nx + x] == w1[y * nx + x + N1]) printf("=");
else printf("−");
}
}
printf("\n");
if(y < ny - N1) {
for(x = N0 ; x < nx ; x++) { /* 縦方向リンク線 /*
if(w1[y * nx + x] == w1[(y + N1) * nx + x]) printf("‖");
else printf("|");
if(x < nx - N1) printf(" ");
else printf("\n");
}
}
}
}
/******************************************************************************
機能:初期化処理(定義情報取得)
引数:なし
戻り値:なし
*****************************************************************************/*
void init(void)
{
int x , y; /* 座標 /*
int i; /* ループの制御変数 /*
int n; /* リンク線の番号 /*
nx = strlen(teigi[N0]); /* 横幅 /*
ny = sizeof(teigi) / sizeof(teigi[N0]); /* 縦長 /*
nxy = nx * ny;
ban = (int *)malloc(sizeof(int) * nxy); /* 盤の領域を確保 /*
if(ban == NULL) {
fprintf(stderr , "malloc error at %d\n" , __LINE__);
exit(EXIT_FAILURE);
}
w1 = (int *)malloc(sizeof(int) * nxy); /* ワークの領域を確保 /*
if(w1 == NULL) {
free(ban);
fprintf(stderr , "malloc error at %d\n" , __LINE__);
exit(EXIT_FAILURE);
}
for(i = N0 ; i < N26 ; i++) se[i].f1 = OFF; /* 始点未出現にする /*
for(y = N0 ; y < ny ; y++) {
for(x = N0 ; x < nx ; x++) {
if(*(teigi[y] + x) == '.') ban[y * nx + x] = NON;
else {
n = *(teigi[y] + x) - 'A'; /* リンク線の番号 /*
if(n > nSe) nSe = n; /* リンク線の個数−1をセット /*
if(se[n].f1 == OFF) { /* 始点の場合 /*
ban[y * nx + x] = n * nxy;
se[n].sx = x; /* 始点X座標 /*
se[n].sy = y; /* 始点Y座標 /*
se[n].sn = ban[y * nx + x]; /* 始点番号 /*
se[n].f1 = ON; /* 始点出現済みにする /*
}
else { /* 終点の場合 /*
ban[y * nx + x] = n * nxy + nxy - N1;
se[n].ex = x; /* 終点X座標 /*
se[n].ey = y; /* 終点Y座標 /*
se[n].en = ban[y * nx + x]; /* 終点番号 /*
}
}
}
}
}
/******************************************************************************
プロトタイプ宣言
*****************************************************************************/*
void sub1(int);
/******************************************************************************
機能:リンク線を伸ばす
引数:
(1) x : X座標
(2) y : Y座標
(3) m : 座標の番号
(4) n : リンク線の番号
戻り値:なし
*****************************************************************************/*
void sub2(int x , int y , int m , int n)
{
int i; /* ループの制御変数 /*
int m1; /* 次の座標番号 /*
int t1; /* 一時変数 /*
t1 = y * nx + x;
for(i = n + N1 ; i <= nSe ; i++) {
if(check(i) == OFF) return; /* 他のリンク線がつながるかチェック /*
}
if(ban[t1] == se[n].en) { /* 終点にたどり着いた場合 /*
if(n == nSe) disp(); /* 全てのリンク線を引いた場合 /*
else sub1(n + N1); /* 次のリンク線へ /*
return;
}
else if(ban[t1] != NON) return; /* 既にリンク線があったら何もせず戻る /*
ban[t1] = m; /* 番号をセットする /*
m1 = m + N1;
if(x > N0) sub2(x - N1 , y , m1 , n); /* 左へ進む /*
if(y > N0) sub2(x , y - N1 , m1 , n); /* 上へ進む /*
if(x < nx - N1) sub2(x + N1 , y , m1 , n); /* 右へ進む /*
if(y < ny - N1) sub2(x , y + N1 , m1 , n); /* 下へ進む /*
ban[t1] = NON;
}
/******************************************************************************
機能:リンク線を伸ばす(始点処理)
引数:
(1) n : リンク線の番号
戻り値:なし
*****************************************************************************/*
void sub1(int n)
{
int x , y; /* 座標 /*
int t1; /* 一時変数 /*
x = se[n].sx; /* リンク線の始点 /*
y = se[n].sy;
t1 = se[n].sn + N1;
if(x > N0) sub2(x - N1 , y , t1 , n); /* 左へ進む /*
if(y > N0) sub2(x , y - N1 , t1 , n); /* 上へ進む /*
if(x < nx - N1) sub2(x + N1 , y , t1 , n); /* 右へ進む /*
if(y < ny - N1) sub2(x , y + N1 , t1 , n); /* 下へ進む /*
}
/******************************************************************************
機能:メイン
引数:なし
戻り値:EXIT_SUCCESS
*****************************************************************************/*
int main(void)
{
init(); /* 初期化 /*
sub1(N0); /* リンク線を引く /*
free(ban); /* 領域を開放 /*
free(w1);
printf("解答:%d通り\n",count); /* 正解を表示 /*
return(EXIT_SUCCESS);
}
| | |