问题 A: 过河问题–搜索树
题目描述
多个囚犯参与者要过河,其中只有监管者一人可以划船。小船每次最多载两人过河。监管者不在时,已有积怨的囚犯可能会斗殴。请问他们该如何安全过河?
假设一开始所有人都在河的左岸,用0表示,如果成功过河,则到达河的右岸,用1表示。
请采用BFS求解,并输出过河过程。
输入
首先输入要过河的人数n(包括监管者和囚犯)
接着输入监管者的编号s(假设每个人的编号从0开始,编号最小的在最右边)
然后输入有积怨的囚犯的对数m
接下来m行,两两输入有积怨的囚犯编号
输出
如有解,输出划船过河方案,即每一步的状态,也就是每个人此时在河的左岸还是右岸。初始状态全部为0。
否则,输出No solution
样例输入1
4
3
2
0 1
1 2
样例输入2
5
4
2
1 3
0 1
扫描二维码关注公众号,回复:
13112473 查看本文章

样例输出1
0000
1010
0010
1011
0001
1101
0101
1111
样例输出2
00000
10010
00010
10011
00001
11001
01001
11101
01101
11111
代码
#include <iostream>
#include <queue>
#include <vector>
#include <stack>
using namespace std;
class node
{
public:
int* boat;
node* father;
node(int n)
{
boat=new int[n];
for(int i=0;i<n;i++)boat[i]=0;//可优化
}
};
class solution
{
public:
int num,boss,pairs;//过河的人数,监管者编号,有仇者对数
int s1[10],s2[10];//有仇者关系数组
vector<node*> visit;//已访问结点
queue<node*> list;//结点队列,bfs
bool is_same(node* temp1)//判断是否到达目标状态
{
for(int i=0;i<num;i++)
if(temp1->boat[i]!=1)return false;
return true;
}
bool is_same(node* temp1,node* temp2)//重载,判断两个状态是否相等
{
for(int i=0;i<num;i++)
if(temp1->boat[i]!=temp2->boat[i])return false;
return true;
}
void put_next(node* temp1,int i)//将子状态压入队列
{
/*初始化子结点*/
node* subnode=new node(num);//应该在堆中开辟
for(int j=0;j<num;j++)
subnode->boat[j]=temp1->boat[j];
subnode->father=temp1;
/*确定子结点的情况*/
int index1=num-boss-1;//boss物理坐标
int index2=i;//数组第i位
if(index2==index1){
//boss自己过河的情况
subnode->boat[index1]=subnode->boat[index1]==1?0:1;
}else if(temp1->boat[index1]==temp1->boat[index2]){
//boss和囚犯在河的同一边的情况
subnode->boat[index1]=subnode->boat[index1]==1?0:1;
subnode->boat[index2]=subnode->boat[index2]==1?0:1;
}else{
//遍历到的情况是boss和囚犯不在河的同一边,这种情况直接跳过
return;
}
/*判定有没有出现过*/
bool flag=false;
for(int j=0;j<visit.size();j++){
//判断子结点有没有出现过
if(is_same(subnode,visit[j])){
flag=true;break;}
}
/*判定会不会打架*/
for(int j=0;j<pairs;j++){
int indexA=num-s1[j]-1;//囚犯1物理地址
int indexB=num-s2[j]-1;//囚犯2物理地址
if((subnode->boat[index1]!=subnode->boat[indexA])&&(subnode->boat[indexA]==subnode->boat[indexB])){
flag=true;
visit.push_back(subnode);//不合理的以后也别加入队列了
break;
}
}
if(!flag)list.push(subnode);//如果没有出现过且囚犯不会打架
}
void print_path(node* temp)
{
stack<node*> bucket;
node *p=temp;
while(p){
bucket.push(p);
p=p->father;
}
while(!bucket.empty()){
for(int i=0;i<num;i++)
cout << bucket.top()->boat[i];
bucket.pop();
cout << endl;
}
}
void serach()
{
node* start=new node(num);
start->father=NULL;//根节点
list.push(start);
while(!list.empty()){
if(is_same(list.front())){
print_path(list.front());return;};//找到路径
visit.push_back(list.front());//标记已经访问
for(int i=num-1;i>=0;i--){
//遍历数组下标
put_next(list.front(),i);//将子状态压入队列
}
list.pop();//弹出队列
}
cout << "No solution";
}
};
int main()
{
solution task;
cin >> task.num;
cin >> task.boss;
cin >> task.pairs;
for(int i=0;i<task.pairs;i++)
cin >> task.s1[i] >> task.s2[i];
task.serach();
return 0;
}
目的
一个笔记(写的有点复杂)