一个人要将一匹狼、一只羊、一筐菜运到河对岸,但是他的船太小了,一次只能带一样过河。当他不在时,狼要吃羊、羊要吃菜。他怎样才能安全地将狼、羊、菜都运过河呢?
Please write a program to find out all the ways to cross the river.
Use four letters to represent the states of man, Wolf, sheep and vegetable respectively:
M means people are there, and. Means people are not there
W means the Wolf is there, and. Means the Wolf is not there
G is for sheep and. Is for sheep
C is for the dish, and. Is for the dish
Use -> to indicate that the ship will go from the left bank to the right bank, use <- to indicate that the ship will go from the right bank to the left bank.
Illustration
If all the vegetables are on the left bank, the state is denoted as
MWGC -> ....
If sheep are transported to the right bank and only wolves and vegetables are left on the left bank, the state is expressed as
.W.C <- M.G.
Input Specification:
The initial state
Termination status
Output Specification:
Output all solutions, if any.
Each solution consists of several lines, each representing a state.
There is a blank line between the different solutions.
If there is no solution, None is printed.
Requirement: Two lines of the same state are not allowed in the output solution.
Sample Input 1:
MWGC -> ....
.... <- MWGC
Sample Output 1:
MWGC -> ....
.W.C <- M.G.
MW.C -> ..G.
...C <- MWG.
M.GC -> .W..
..G. <- MW.C
M.G. -> .W.C
.... <- MWGC
MWGC -> ....
.W.C <- M.G.
MW.C -> ..G.
.W.. <- M.GC
MWG. -> ...C
..G. <- MW.C
M.G. -> .W.C
.... <- MWGC
Sample Input 2:
.W.. <- M.GC
M.GC -> .W..
Sample Output 2:
.W.. <- M.GC
MWG. -> ...C
..G. <- MW.C
M.GC -> .W..
.W.. <- M.GC
MW.C -> ..G.
...C <- MWG.
M.GC -> .W..
Sample Input 3:
MWG. -> ...C
MWG. -> ...C
Sample Output 4:
None
Sample Input 4:
MWG. -> ...C
.WG. -> M..C
Sample Output 4:
None
Note: In order to keep the sequence of output solutions consistent, people are required to explore the following sequence each time they cross the river:
Cross the river directly (without carrying anything)
Take the Wolf across the river
Take the sheep across the river
Take food across the river
/* 人狼羊菜过河 */
/* ATTENTION */
/* This program runs in C++ mode, if this program can't run correctly in your computer, please filling-in this sentence "-std=c++11" in Compiler Settings */
/* Data Structures and Algorithm */
/*
* The program algorithm is ergodic exhaustive plus backtracking.
* The program identifies each output statement with a number, and every item has two and only two states, so the program tries to solve the labeling program with binary numbers.
*/
#include<stdio.h>
#include<math.h>
#define Radix 16
void Scan(); // scan the orginal number and save the destination
void print_Path(); // print the correct path from the first step to the last
void check_Result(); // there is result or not showed by flag (flag = 0 --> None)
void moving(); // moving objects by using method
int get_Bin(); // translate the Objects array into an binary number, and output in decimal
int get_Bin(int move); // get the changing number of the move
int islegalScan(); // judge it is a legally scan (illegal--0 legal--1)
int check(int Bin); // get the result by checking method (false--0 true--1 correct--2)
int survive(int way); // return the remider to show they are in the same state (false--0 true--1)
/* Object Move */
void method0(); // move M
void method1(); // move M & W
void method2(); // move M & G
void method3(); // move M & C
/* Stack */
void push(int method); // push the method into the stack
void pop(); // pop method from the stack
int flag = 0; // IOF one --> flag = 0 else --> flag = 1;
int top = -1; // top of the stack
int stack[Radix]; // the stack of moving
int Objects[4]; // M W G C 0 -- Left 1 -- Right
int checkArray[Radix] = {0}; // pow(2, 4) 0 --> uncollected 1 --> collected
int pathArray[Radix]; // record the path of the orginal to the destination
int original = 15; // create an immutable primitive variable for multi-mode output
int destination = 15; // initializing to 15 tends to change it (Minus each of the null -- '.')
//----main--------
int main(void)
{
Scan();
if(islegalScan())moving();
check_Result();
return 0;
}
//----main--------
void Scan()
{
int i;
char ch;
for(i=0; i<13; i++)
{
ch = getchar();
if(i < 4) {
if(ch == '.') {
Objects[i] = 0;
original -= pow(2, 3-i);
}
else Objects[i] = 1;
}
}
for(i=0; i<13; i++)
{
ch = getchar();
if(i < 4) {
if(ch == '.')destination -= pow(2, 3-i);
}
}
}
int islegalScan()
{
// both the original and the destination are the same or (the original or the destination) is a wrong state
if(original == destination || check(original) == 0 || check(destination) == 0)return 0;
checkArray[original] = 1;
return 1;
}
int check(int Bin)//false --> 0 true --> 1 correct --> 2
{
int n = Bin;
// ATTENTION the false checking should before the correct checking
if(n == 3 || n == 6 || n == 7 || n == 8 || n == 9 || n == 12)return 0; // false method
else if(n == destination)return 2; // correct path
else return 1; // true
}
int survive(int way)
{
switch(way) {
case 0: return 1;break; // M
case 1: if(Objects[0] == Objects[1])return 1; break; // M & W
case 2: if(Objects[0] == Objects[2])return 1; break; // M & G
case 3: if(Objects[0] == Objects[3])return 1; break; // M & C
}
return 0;
}
void moving()
{
int i;
int check_result = check( get_Bin() );
if(check_result == 0) { // false method
checkArray[get_Bin()] = 0;
pop();
return;
}
if( check_result == 2 ) { // correct method
int temp = original; // to leave original unchanged, create a new variable
int change_Bin;
for(i=0; i<=top; i++)
{
pathArray[i] = temp; // store the path in positive order
change_Bin = get_Bin(stack[i]); // put the changing number of the method into "change_Bin"
if(temp > 7) { // from Right to Left --- plus
temp -= change_Bin;
}else {
temp += change_Bin; // from Left to Right --- minus
}
}
pathArray[i] = temp;
print_Path(); // print the path
checkArray[get_Bin()] = 0; // after finish the print, as the "check_result == 0"
pop(); // ready to next print_Path (if there are diffdrent ways)
return;
}
for(i=0; i<4; i++)
{
if(survive(i))push(i); // check are they in the same state
else continue;
if(checkArray[get_Bin()] == 1) { // have already appeared, false
pop();
continue;
}else {
checkArray[get_Bin()] = 1; // from 0 to 1, be enclosed
}
moving(); // recursion to run through all
}
checkArray[get_Bin()] = 0; // this layer traversal is complete, pop out to the next layer
pop();
}
int get_Bin()// 0000 to 1111 (Binary system return by decimalism)
{
int result = 0;
if(Objects[0]) result += 8; // 1...
if(Objects[1]) result += 4; // .1..
if(Objects[2]) result += 2; // ..1.
if(Objects[3]) result += 1; // ...1
return result;
}
int get_Bin(int move)// result represent the changing number of different methods
{
int result = 0;
switch(move)
{
case 0: result = 8; break;
case 1: result = 12;break;
case 2: result = 10;break;
case 3: result = 9; break;
default: ;
}
return result;
}
/* Object Move */
void find_Method(int n)
{
switch(n)
{
case 0: method0();break;
case 1: method1();break;
case 2: method2();break;
case 3: method3();break;
default: ;
}
}
void method0()// M
{
if(Objects[0] == 1)Objects[0] = 0;
else Objects[0] = 1;
}
void method1()// M & C
{
if(Objects[0] == 1)Objects[0] = 0;
else Objects[0] = 1;
if(Objects[1] == 1)Objects[1] = 0;
else Objects[1] = 1;
}
void method2()// M & G
{
if(Objects[0] == 1)Objects[0] = 0;
else Objects[0] = 1;
if(Objects[2] == 1)Objects[2] = 0;
else Objects[2] = 1;
}
void method3()// M & W
{
if(Objects[0] == 1)Objects[0] = 0;
else Objects[0] = 1;
if(Objects[3] == 1)Objects[3] = 0;
else Objects[3] = 1;
}
/* Stack */
void push(int method)
{
stack[++top] = method;
find_Method(stack[top]); // rebound
}
void pop()
{
find_Method(stack[top--]);
}
/* Print */
void print_Path()
{
int i;
if(flag == 0)flag = 1;
else printf("\n");
for(i=0; i<=top+1; i++)
{
switch( pathArray[i] ) { // show all rather than required output
case 0 : printf(".... <- MWGC\n");break;
case 1 : printf("...C <- MWG.\n");break;
case 2 : printf("..G. <- MW.C\n");break;
case 3 : printf("..GC <- MW..\n");break;
case 4 : printf(".W.. <- M.GC\n");break;
case 5 : printf(".W.C <- M.G.\n");break;
case 6 : printf(".WG. <- M..C\n");break;
case 7 : printf(".WGC <- M...\n");break;
case 8 : printf("M... -> .WGC\n");break;
case 9 : printf("M..C -> .WG.\n");break;
case 10: printf("M.G. -> .W.C\n");break;
case 11: printf("M.GC -> .W..\n");break;
case 12: printf("MW.. -> ..GC\n");break;
case 13: printf("MW.C -> ..G.\n");break;
case 14: printf("MWG. -> ...C\n");break;
case 15: printf("MWGC -> ....\n");break;
default: ;
}
}
}
void check_Result()
{
if(flag == 0)printf("None");
}
代码人 ~ 代码魂 ~ 此生钟爱代码神 ~ Big_Kiss~