Week2 作业

A-Maze

题目

东东有一张地图,想通过地图找到妹纸。地图显示,0表示可以走,1表示不可以走,左上角是入口,右下角是妹纸,这两个位置保证为0。既然已经知道了地图,那么东东找到妹纸就不难了,请你编一个程序,写出东东找到妹纸的最短路线。

Input

输入是一个5 × 5的二维数组,仅由0、1两数字组成,表示法阵地图。Output  输出若干行,表示从左上角到右下角的最短路径依次经过的坐标,格式如样例所示。数据保证有唯一解。

Sample Input

0 1 0 0 0
0 1 0 1 0
0 1 0 1 0
0 0 0 1 0
0 1 0 1 0

Sample Output

(0, 0)
(1, 0)
(2, 0)
(3, 0)
(3, 1)
(3, 2)
(2, 2)
(1, 2)
(0, 2)
(0, 3)
(0, 4)
(1, 4)
(2, 4)
(3, 4)
(4, 4)

Hint

坐标(x, y)表示第x行第y列,行、列的编号从0开始,且以左上角为原点。  另外注意,输出中分隔坐标的逗号后面应当有一个空格。

做法

用结构体coo记录点的坐标,mapp数组保存地图,mark数组标记是否走过,走过记为1,没有记为0。数组xx和yy用来完成迷宫某一点上下左右的走法。用bfs的思想走迷宫,将起点放入队列,探索可能的走法并入队,之后每次取出一点直到队列为空或走到终点停止,得到的一定就是最短路径。
问题是如何把路径保存下来,我这里用队列来保存路径,bfs的队列中每一个元素都是队列,这样需要事先创建一个结构体path,其成员就是用来保存路径的coo型队列。这样bfs每次从队列中取出一个元素实际取的是一条队列保存的路径,再从路径末尾取出一点,探索可能的走法并入队。最终的返回值是成功到达终点的路径队列。

代码

#include<iostream>
#include<queue>
using namespace std;

int mapp[6][6];
int mark[6][6];//是否走过 
int xx[]={0,0,1,-1};
int yy[]={1,-1,0,0};

struct coo
{
	int x,y;//点的坐标 
};

struct path
{
	queue<coo> d;//路线坐标 
};

path bfs()
{
	path p;
	coo s;//起点 
	s.x=0,s.y=0;
	mark[0][0]=1;
	p.d.push(s);
	queue<path> qu;
	qu.push(p);
	while(!qu.empty())
	{
		path t=qu.front();
		coo s1=t.d.back();
		if(s1.x==4&&s1.y==4)//到达终点 
		   return t;
		for(int i=0;i<4;i++)
		{
			path t1=t;
			coo s2=t.d.back();
			s2.x=s2.x+xx[i];
			s2.y=s2.y+yy[i];
			if(s2.x>=0&&s2.x<5&&s2.y>=0&&s2.y<5&&mark[s2.x][s2.y]==0&&mapp[s2.x][s2.y]==0)
			{
				mark[s2.x][s2.y]=1;
				t1.d.push(s2);
				qu.push(t1);
			}
		}
		qu.pop();
	}
	return qu.front();
}


int main()
{
	for(int i=0;i<5;i++)
	 for(int j=0;j<5;j++)
	   cin>>mapp[i][j];
	   
	path pt=bfs();
	while(!pt.d.empty())
	{
		coo st=pt.d.front();
		pt.d.pop();
		cout<<"("<<st.x<<", "<<st.y<<")"<<endl;
	}
	return 0;
}

B - Pour Water

题目

倒水问题 “fill A” 表示倒满A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯并且把B杯倒满或A倒空。

Input

输入包含多组数据。每组数据输入 A, B, C 数据范围 0 < A <= B 、C <= B <=1000 、A和B互质。

Output

你的程序的输出将由一系列的指令组成。这些输出行将导致任何一个罐子正好包含C单位的水。每组数据的最后一行输出应该是“success”。输出行从第1列开始,不应该有空行或任何尾随空格。

Sample Input

2 7 5
2 7 4

Sample Output

fill B
pour B A
success
fill A
pour A B
fill A
pour A B
success

Notes

如果你的输出与Sample Output不同,那没关系。对于某个"A B C"本题的答案是多解的,不能通过标准的文本对比来判定你程序的正确与否。 所以本题由 SPJ(Special Judge)程序来判定你写的代码是否正确。

做法一

用小杯子往大杯子里倒水,大杯子倒满就把里面的水倒掉,相当于A%B,2A%B,3A%B……就能得到C容量的水(然鹅并不能通过测试)
代码

#include<iostream>
#include<queue>
using namespace std;

int main()
{
	int a,b,c;
	int b1=0;
	while(cin>>a>>b>>c)
	{
		while(b1!=c)
		{
			if(b1+a<b)
			{
				b1=b1+a;
				cout<<"fill A"<<endl;
				cout<<"pour A B"<<endl;
			}
			else if(b1+a>=b)
			{
				b1=b1+a-b;
				cout<<"fill A"<<endl<<"pour A B"<<endl<<"empty B"<<endl<<"pour A B"<<endl;
			}
		 }
		 cout<<"success"<<endl; 
	}
	return 0;
 } 

做法二

倒水问题是一种隐式图问题,AB杯子里的水容量可以看成图的坐标,比如杯子都为空时是点(0,0),A杯有2容量的水、B杯有3容量的水是点(2,3)……,这就可以转换成上面的迷宫问题,终点就是AB其中一个杯子的水达到了C容量。
迷宫到达每一点都有上下左右四种走法,并且需要保证点未走过、没有障碍物。而倒水的每种状态有六种选择:①A杯不满,倒满A杯 ②B杯不满,倒满B杯 ③A杯有水,倒空A杯 ④B杯有水,倒空B杯 ⑤A杯有水B杯未满,A倒入B(可能倒不完)⑥B杯有水A杯不满,B倒入A(可能倒不完)。考虑这些情况也需要判断杯中水的容量状态是否到达过。
这就可以转换成上面的迷宫问题,只不过是把for循环里的上下左右四种走法换成倒水的六种方法。另外,需要记录倒水步骤,可以在结构体cup里加一个int型成员,用123456对应倒水的六种方式。

代码

#include<iostream>
#include<queue>
#include<string.h>
using namespace std;

struct cup
{
	int a,b;
	int state;
};
struct path
{
	queue<cup> d;
}; 

int mark[109][109];

path bfs(int A,int B,int C)
{
	memset(mark,0,sizeof(mark));//0表示此状态未达到
	path p;
	cup s;//起点
	s.a=0;s.b=0;
	mark[0][0]=1;
	p.d.push(s);
	queue<path> qu;
	qu.push(p);
	while(!qu.empty())
	{
		path t=qu.front();
		cup s=t.d.back();
		if(s.a==C||s.b==C)
		{
			return t;
		}
		if(s.b<B)
		{
			path t1=t;
			cup s2;
			s2.b=B;//倒满b杯
			s2.a=s.a;
			if(mark[s2.a][s2.b]==0)
			{
				s2.state=1;
				mark[s2.a][s2.b]=1;
				t1.d.push(s2);
				qu.push(t1);
			 } 
		}
		if(s.b>0)
		{
			path t1=t;
			cup s2;
			s2.b=0;//倒空b杯
			s2.a=s.a;
			if(mark[s2.a][s2.b]!=1)
			{
				s2.state=2;
				mark[s2.a][s2.b]=1;
				t1.d.push(s2);
				qu.push(t1);
			 } 
		}
		if(s.a<A)
		{
			path t1=t;
			cup s2;
			s2.b=s.b; 
			s2.a=A;//倒满a杯 
			if(mark[s2.a][s2.b]!=1)
			{
				s2.state=3;
				mark[s2.a][s2.b]=1;
				t1.d.push(s2);
				qu.push(t1);
			 } 
		}
		if(s.a>0)
		{
			path t1=t;
			cup s2;
			s2.b=s.b;
			s2.a=0;//倒空a杯 
			if(mark[s2.a][s2.b]!=1)
			{
				s2.state=4;
				mark[s2.a][s2.b]=1;
				t1.d.push(s2);
				qu.push(t1);
			 } 
		 } 
		 if(s.a>0&&s.b<B)
		 {
		 	if(s.a+s.b>B)
		 	{
		 		path t1=t;
			cup s2;
			s2.b=B;
			s2.a=s.a+s.b-B;//倒满b杯a杯剩有水 
			if(mark[s2.a][s2.b]!=1)
			{
				s2.state=5;
				mark[s2.a][s2.b]=1;
				t1.d.push(s2);
				qu.push(t1);
			 } 
			 }
			 else
			 {
			 	path t1=t;
			cup s2;
			s2.b=s.a+s.b;
			s2.a=0;//倒入b杯后a杯没水 
			if(mark[s2.a][s2.b]!=1)
			{
				s2.state=5;
				mark[s2.a][s2.b]=1;
				t1.d.push(s2);
				qu.push(t1);
			 } 
			 }
		  }
		  if(s.a<A&&s.b>0)
		  {
		  	if(s.a+s.b>A)
		  	{
		  		path t1=t;
			cup s2;
			s2.b=s.a+s.b-A;//倒入a杯后b杯有剩余 
			s2.a=A;
			if(mark[s2.a][s2.b]!=1)
			{
				s2.state=6;
				mark[s2.a][s2.b]=1;
				t1.d.push(s2);
				qu.push(t1);
			 } 
		   }
			 else
			 {
			 	path t1=t;
			cup s2;
			s2.b=0;//倒入a杯后b杯无剩余 
			s2.a=s.a+s.b;
			if(mark[s2.a][s2.b]!=1)
			{
				s2.state=6;
				mark[s2.a][s2.b]=1;
				t1.d.push(s2);
				qu.push(t1);
			 } 
			  }
		   }
		    qu.pop();
	 } 
	 return qu.front();
}

int main()
{
	int a1,b1,c1;
	while(cin>>a1>>b1>>c1)
	{
		path pt=bfs(a1,b1,c1);
		while(!pt.d.empty())
		{
			cup st=pt.d.front();
			pt.d.pop();
			if(st.state==1) cout<<"fill B"<<endl;
			else if(st.state==2) cout<<"empty B"<<endl;
			else if(st.state==3) cout<<"fill A"<<endl;
			else if(st.state==4) cout<<"empty A"<<endl;
			else if(st.state==5) cout<<"pour A B"<<endl;
			else if(st.state==6) cout<<"pour B A"<<endl;
		}
		cout<<"success"<<endl;
		
	}
	return 0;
}
发布了6 篇原创文章 · 获赞 0 · 访问量 88

猜你喜欢

转载自blog.csdn.net/weixin_44359234/article/details/104679212