65,183
社区成员




#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define MAX_PERSON 9
#define MAX_BEAST 9
const int Left = 0, Right = 1;
struct Record{
int person;
int beast;
int direction;
};
void printRecord(const vector<Record>& v)
{
for(int i = 0, s = v.size(); i < s; ++i){
printf("%d times: ", i+1);
if(v[i].person > 0) printf("%d people", v[i].person);
if(v[i].person > 0 && v[i].beast > 0) printf(" and ");
if(v[i].beast > 0) printf("%d beast", v[i].beast);
if(v[i].direction == Left) puts(" go from right bank to left bank");
else puts(" go from left bank to right bank");
}
}
int totalPerson, totalBeast, boatCapacity; //known conditions
bool state[2][MAX_PERSON+1][MAX_BEAST+1]; //state: left bank's person and beast number with the boat's position
bool goAcrossRiver(const int personOnShore, const int beastOnShore, int atBank, vector<Record>& v)
{
//all have crossed the river
if(atBank == Right && personOnShore == totalPerson && beastOnShore == totalBeast){
return true;
}
//figure out how many people and beasts on other side
int personOtherSide = totalPerson - personOnShore;
int beastOtherSide = totalBeast - beastOnShore;
//mark state traversed
if(atBank == Left) state[Left][personOnShore][beastOnShore] = true;
else state[Right][personOtherSide][beastOtherSide] = true;
//continue to drive boat to other side
Record tmp;
for(int personToGo = 0; personToGo <= personOnShore; ++personToGo){
for(int beastToGo = 0; beastToGo <= beastOnShore; ++beastToGo){
//if too many to get on boat
if(personToGo + beastToGo > boatCapacity) break;
//if no one to drive
if(personToGo == 0 && beastToGo == 0) continue;
//if beast number > person number on this side
if(personOnShore - personToGo > 0 && beastOnShore - beastToGo > personOnShore - personToGo) continue;
//if beast number > person number on other side
if(personOtherSide + personToGo > 0 && beastOtherSide + beastToGo > personOtherSide + personToGo) continue;
//if next state has been traversed
if(atBank == Left && state[Right][personOnShore - personToGo][beastOnShore - beastToGo]) continue;
if(atBank == Right && state[Left][personOtherSide + personToGo][beastOtherSide + beastToGo]) continue;
//only in this case, can crossing river be done, and record before crossing
tmp.person = personToGo;
tmp.beast = beastToGo;
tmp.direction = !atBank;
v.push_back(tmp);
if(goAcrossRiver(personOtherSide + personToGo, beastOtherSide + beastToGo, !atBank, v)) return true;//a path has been found
v.pop_back();
}
}
//no path from current state to final state
return false;
}
int main()
{
vector<Record> rec;
for(int i = 1; i <= MAX_PERSON; ++i){
totalPerson = totalBeast = boatCapacity = i;
memset(state, false, sizeof(state));
printf("%d people and %d beasts want to cross the river:\n", totalPerson, totalBeast);
if(goAcrossRiver(totalPerson, totalBeast, Left, rec)) printRecord(rec);
else puts("No way!");
getchar();
}
return 0;
}
最后,需要注意的是,由于DFS搜索的盲目性,可能得到的结果不是最优的