/**************************************************************************
狼と山羊とキャベツと男 (幅優先探索)
**************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#define MAN 0
#define WOLF 1
#define GOAT 2
#define CABBAGE 3
#define TimeMax 50
int state[TimeMax][5]; /* 男がいる側の状態
state[t][4]が 0なら左岸 1なら右岸 */
int prev_state[TimeMax]; /* 過去の状態の履歴 */
/**************************************************************************
状態の表示
引数 state[i] : 左岸もしくは右岸の状態
state[i]の配列の内容に応じて状態を表示する
(例) state[i]={1,1,1,1}ならば [ 男 狼 山羊 キャベツ ]
state[i]={1,0,1,0}ならば [ 男 山羊 ]
state[i]={0,0,0,0}ならば [ ]
**************************************************************************/
void print_state(int state[4])
{
/*** この部分を自分で作成する ***/
static char *str[4] = { "男", "狼", "山羊", "キャベツ" };
int i;
for(i = 0; i < 4; i++) {
if(state[i] == 1) {
}
}
}
/**************************************************************************
結果の表示
引数 t : ステップ数
tステップ目の結果を表示する
ステップ数: [ 左岸の状態 ] [ 右岸の状態 ]
(例) 0: [ 男 狼 山羊 キャベツ ] [ ]
1: [ 狼 山羊 ] [ 男 キャベツ ]
**************************************************************************/
void print_ans(int t)
{
int i;
int right[4];
int left[4];
/* prev_state[t]に値が入っていれば状態を表示 */
if(prev_state[t] != -1) {
print_ans(prev_state[t]);
}
/* 男が右岸にいる場合
right[] に state[t][] をコピー & left[]のデータを生成 */
/*** この部分を自分で作成する ***/
if(state[t][4] == 1) {
for(i = 0; i < 4; i++) {
right[i] = state[t][i];
left[i] = 1 - state[t][i]; /* 0,1反転 */
}
}
/* 男が左岸にいる場合
left[] に state[t][] をコピー & right[]のデータを生成 */
/*** この部分を自分で作成する ***/
else {
for(i = 0; i < 4; i++) {
left[i] = state[t][i];
right[i] = 1 - state[t][i]; /* 0,1反転 */
}
}
/* tステップの状態を表示する
[ヒント] print_state()の関数が正しく作成されていれば
print_state(left_side[t]); で tステップ目の左岸の状態、
print_state(right_side[t]); で tステップ目の右岸の状態
が表示できる */
/*** この部分を自分で作成する ***/
i = 1;
while((t = prev_state[t]) != -1) {
i++;
}
print_state(left);
print_state(right);
}
/**************************************************************************
状態のチェック
引数 T : ステップ数
・狼と山羊、山羊とキャベツを残した状態でもなく、既に探索された状態
でもなければ 1を返す
・それ以外は 0を返す
**************************************************************************/
int check_state(int T)
{
int i, t;
int now_state[4]; /* 男がいない側の現在の状態 */
int count;
/* 男がいない側の現在の状態をstate[T][]から生成し、now_state[]に代入 */
/*** この部分を自分で作成する ***/
for(i = 0; i < 4; i++) {
now_state[i] = 1 - state[T][i]; /* 0,1反転 */
}
/* 狼と山羊 もしくは 山羊とキャベツが一緒にないかをチェック
あれば0を返す */
/*** この部分を自分で作成する ***/
if((now_state[WOLF] + now_state[GOAT] == 2)
|| (now_state[GOAT] + now_state[CABBAGE] == 2)) {
return 0;
}
/* 過去に同じ状態がないかをチェック あれば0を返す
[ヒント] state[t][i](tステップ目の状態)と
state[T][i](現在の状態)を比較してチェック */
for(t = 0; t < T; t++) {
/*** この部分を自分で作成する ***/
for(i = 0; i < 5; i++) {
if(state[t][i] != state[T][i]) {
break;
}
}
if(i == 5) {
return 0;
}
}
/* いずれにも該当しなければ1を返す */
return 1;
}
/**************************************************************************
幅優先探索
**************************************************************************/
void search()
{
int i, j;
/* r の位置にあるデータを取り出して、新しい状態を生成できたら、w の位置
に書き込む */
static int r = 0;
static int w = 1;
int now_state[5]; /* 男がいる側の現在の状態 */
int new_state[5]; /* 次のステップの男がいる側の状態 */
for(; r < w; r++) {
/* now_state[]に stage[r][]をコピー */
for(i = 0; i < 5; i++) {
now_state[i] = state[r][i];
}
for(i = 0; i < 4; i++) { /* 0: 男 1: 狼 2: 山羊 3: キャベツ を順に調べる */
if(now_state[i] == 1) { /* 移動できるのであれば(男と同じ側にいれば) */
/* iと男を移動(iが0の場合は男のみ移動)した後の状態を
new_state[]に格納
[ヒント] 現在の状態 (state[])をnew_state[]にコピーし,
iと男が移動した場合に値がどのように変化するかを設定 */
/*** この部分を自分で作成する ***/
for(j = 0; j < 5; j++) {
new_state[j] = 1 - now_state[j]; /* 0,1反転 */
}
new_state[MAN] = 1;
new_state[i] = 1;
/* state[w][]としてnew_state[]を保存 */
for(j = 0; j < 5; j++) {
state[w][j] = new_state[j];
}
/* prev_state[w]としてrを保存 */
prev_state[w] = r;
/* iと男を移動(iが0の場合は男のみ移動)した後の状態が有効かどうかを
チェック */
if(check_state(w)) {
/* 右岸にすべてが移動していれば 結果を表示して終了 */
if( /*** この部分を自分で作成する ***/
(new_state[MAN] +
new_state[WOLF] +
new_state[GOAT] +
new_state[CABBAGE] + new_state[4]) == 5) {
print_ans(w);
}
w++;
}
}
}
}
}
/**************************************************************************
メインプログラム
**************************************************************************/
int main()
{
int i, t;
/* 初期化 */
for(i = 0; i < 4; i++) {
state[0][i] = 1; /* 最初はすべて左岸に(男と一緒に)いる */
}
state[0][4] = 0; /* 男は左側にいるので0にセット */
for(t = 0; t < TimeMax; t++) {
prev_state[t] = -1;
}
/* 探索 */
search();
return 0;
}