程序设计思维与实践week2 作业一

一.1:maze 关于地图的最短路径问题
(1):问题描述:
本题输入数据为一个5*5的地图,问题是求得左上角(0,0)到右下角(5,5)的最短路径,并输出途径的地图网格,其中输入数据中0代表可以走,1代表不可以走。
(2):思路
这道题很明显可以用bfs进行解题,为了解题的简单我为地图新增了墙壁,就是在地图最外围新增一圈(1,1);也为了输出的简便,我们从终点开始向起点进行反向遍历,这样结果输出的时候直接就是正向的路径,比较省力。

#include <iostream>
#include<queue> 
#include<algorithm>
#include<string.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
struct point
{
  int x,y;	
  point(){
  };
  point(int x,int y)
  {
  	this->x=x;
  	this->y=y;
  };
};
queue<point> Q;
bool vis[7][7];
int a[7][7];
int sx,sy,tx,ty;
int dx[]={0,0,1,-1};
int dy[]={-1,1,0,0};
//queue<point> P;
point C[7][7];//point结构体必须有空构造 
void bfs(point &A,point &B)//输入起始点 ,并记录路径,A是终点,B是起点 
{
	point t;
	t.x=5;t.y=5;
	Q.push(t);
//	P.push(t);
	vis[5][5]=true;
	C[A.x][A.y]=A;
	while(!Q.empty())
	{
		point now=Q.front();
		Q.pop();
			if(now.x==1&&now.y==1)//到起点
			{
				
				return;
			}
		for(int i=0;i<4;i++)
		{
			int x=now.x+dx[i];
			int y=now.y+dy[i];//进行上下左右的移动

			if(a[x][y]==0&&vis[x][y]==false)//没有到过且可以走
			{
				vis[x][y]=true;
				point t1;
				t1.x=x;t1.y=y;
				Q.push(t1);
				C[x][y]=now;//把现在的点输入到路径中
			}
		}
	}
	
}
int main(int argc, char** argv) 
{
	for(int i=0;i<7;i++)
	{
		a[0][i]=1;
		a[i][0]=1;
		a[i][6]=1;
		a[6][i]=1;
	}//可以自己设置n,m代表地图大小进行输入
	memset(vis,false,sizeof(vis));
	for(int i=1;i<6;i++)
	{
		for(int t=1;t<6;t++)
		{
			cin>>a[i][t];
		}
	}

	point begins(1,1),ends(5,5);
	bfs(ends,begins);
	point t(1,1);
	cout<<"(0, 0)"<<endl;
while(t.x!=5||t.y!=5)
	{
		t=C[t.x][t.y];
	     cout<<'('<<t.x-1<<", "<<t.y-1<<')';
         if(t.x==5&&t.y==5)
         {
         	continue;
		 }
		 else
		 {
		 	cout<<endl;
		 }
	}
	return 0;
}

一.2:pour water

(1):问题描述:
输入三个数据,前两个代表可用的两个杯子的容量,其中A与B杯互质,A<=B;第三个数据就是所求的水的容量,需要用那两个允许使用的杯子进行目标的求解,其实这也是个地图的问题,更确切地说是隐式图
(2):思路 这道题的思路和平时代的bfs基本一致只不过状态多了一些,有六个fill A,fill B,pour A B,pour B A,empty A,empty B。

#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<string.h>
using namespace std;
struct status
{
	int a,b;
	bool operator<(const status &s)const
	{
		return a!=s.a?a<s.a:b<s.b;
	}
};

int AA[1005][2],a1=0;
void print(status &p,map<status,status> & from)
{
	if(from.find(p)==from.end()||(p.a==0&&p.b==0))
	{
		return;
	}
	print(from[p],from);
	AA[a1][0]=p.a;
	AA[a1][1]=p.b;
		a1++;
}
void refresh(status &s,status &t,map<status,status> &from,queue<status> &Q)//判断是否能加入
{
	if(from.find(t)==from.end())
	{
		from[t]=s;
		Q.push(t);
	}
}
void bfs(int A,int B,int C)
{
	queue<status> Q;
    map<status,status>from;
	status s,t;
	s.a=0;s.b=0;
	Q.push(s);
	while(!Q.empty())
	{
		s=Q.front();
		Q.pop();
		if(s.a==C||s.b==C)
		{
			print(s,from);
		    for(int i=0;i<a1;i++)//通过判断当前点与前一个点的关系来判断输出的内容
		    {
			    if(i==0)
			    {
			    	if(AA[0][0]==0)
			    	{
			    		cout<<"fill B"<<endl;
					}
					if(AA[0][1]==0)
					{
						cout<<"fill A"<<endl;
					}
				}
				else
				{
		            if((AA[i][0]+AA[i][1])==(AA[i-1][0]+AA[i-1][1]))
		            {
		            	if(AA[i][0]>AA[i-1][0])
		            	{
		            		cout<<"pour B A"<<endl;
						}
						if(AA[i][1]>AA[i-1][1])
						{
							cout<<"pour A B"<<endl;
						}
					}
					else
					{
				    	if(AA[i][0]>AA[i-1][0])
		            	{
		            		cout<<"fill A"<<endl;
						}
						if(AA[i][1]>AA[i-1][1])
						{
							cout<<"fill B"<<endl;
						}
						if(AA[i][0]!=0&&AA[i][0]==AA[i-1][0]&&AA[i][1]==0)
						{
							cout<<"empty B"<<endl;
						}
						if(AA[i][1]!=0&&AA[i][1]==AA[i-1][1]&&AA[i][0]==0)
						{
							cout<<"empty A"<<endl;
						}
					}
				}
		    }
		    a1=0;
		    memset(AA,0,sizeof(AA));
			cout<<"success"<<endl;
			return;
		}
		if(s.a>0)
		{
			t.a=0;
			t.b=s.b;
			refresh(s,t,from,Q);
		}
		if(s.b>0)
		{
			t.b=0;
			t.a=s.a;
			refresh(s,t,from,Q);
		}
		if(s.a<A)
		{
			t.a=A;
			t.b=s.b;
			refresh(s,t,from,Q);
			if(s.b!=0)
			{
				if(s.a+s.b<=A)
				{
					t.a=s.a+s.b;
					t.b=0;
					refresh(s,t,from,Q);
				}
				else
				{
					t.a=A;
					t.b=s.a+s.b-A;
					refresh(s,t,from,Q);
				}
			 } 
		}
		if(s.b<B)
		{
			t.a=s.a;
			t.b=B;
			refresh(s,t,from,Q);
			if(s.a!=0)
			{
				if(s.a+s.b<=B)
				{
					t.a=0;
					t.b=s.a+s.b;
					refresh(s,t,from,Q);
				}
				else
				{
					t.a=s.a+s.b-B;
					t.b=B;
					refresh(s,t,from,Q);
				}
			}
		}
	 } 
	 cout<<"-1"<<endl;
}
int main()
{
	int a,b,c;
	while(cin>>a&&a!=EOF)
	{
		cin>>b>>c;
		bfs(a,b,c);
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值