西南交大_算法实验5.3

文章描述了一个城市规划问题,涉及计算从城市左下角到右上角穿过大厦的最短路径数量。给定城市尺寸和大厦信息,通过动态规划算法计算不同路径数。样例输入和输出展示了算法的应用,并提供了伪代码和实际程序代码来解决这个问题。时间复杂度为O(B*m*n),其中B是大厦数量,m和n是城市尺寸。
摘要由CSDN通过智能技术生成

实验5.3某城市四面环水,只有左下角和右上角有一座可以到达城市的桥。城市被分成M*N个方形的房子,房子之间可以通路,如图5-4。随着城市的不断发展,原来的小房子逐渐被高楼大厦所取代,每座大厦可能会占用好几个小的房子,但仍保留原来的街道风格,如图5-4所示。

设左下角的坐标为(1,1),右上角坐标为(m, n),城市大厦采用左下角坐标和大厦占用的水平小房子数量和垂直小房子数量来描述。编写程序计算某人从左下角以最短的距离到到右上角一共有多少种不同的路径。

输入:

有多个测试用例。每个测试用例的第一行包含两个整数m, n,表示原来的城市垂直和水平方向上有多少个小房子。第2行为整数B,表示大厦的数量。其后

有B行,每一行包含4个整数x, y,z,b,分别表示大厦左下角坐标以及大厦垂直和水平方向上占用的小房子的数量。

输出:每一组测试数据输出一个整数,也就是从左下角到右上角总的路径数。样例输入:

5 6

1

2 4 3 2

样例输出:192

实验预习:

(1)图5-4中,设从左下角以最短的距离到达A1点的路径数为X1,到达A2的路径数为X2,求从左下角以最短距离到达B点的路径数为多少?

(2)图5-4中,设从左下角以最短的距离到C1点的路径数为Y1,到达C2的路径数为Y2,求从左下角以最短距离到达D点的路径数为多少?

(3)图5-4中,基于(1)的假设,求从左下角以最短路径到达C1, C2点的路径是多少?

(4)设计算法求解该问题,写出算法的伪代码,并分析算法的复杂度。

(5)根据算法,分析样例输入情况下的求解过程,写出求解过程中主要变量的变化过程。

(6)编写程序求解上述问题

4.1.1 1到3小题

(1)图5-4中,设从左下角以最短的距离到达A1点的路径数为X1,到达A2的路径数为X2,从左下角以最短距离到达B点的路径数为X1+ X2

(2)图5-4中,设从左下角以最短的距离到C1点的路径数为Y1,到达C2的路径数为Y2,求从左下角以最短距离到达D点的路径数为Y1+ Y2

(3)图5-4中,基于(1)的假设,求从左下角以最短路径到达C1, C2点的路径分别是X1+ 3、4X1+ 6X2+5

4.1.2 伪代码及时间复杂度

伪代码:

输入:第一行,m, n,第2行为整数B。其后有B行,每一行包含4个整数x, y,z,b

输出: dp[m+1][n+1]

  1. Begin
  2. for 0<j<=m+1,0<k<=n+1 do
  3. Obstacle[j][k]←0,dp[j][k]←0;
  4. for 0<i<B,0<j<=m+1,0<k<=n+1 do
  5. begin
  6. tempm←B[i].x,tempn←B[i].y,tm←B[i].z,tn←B[i].b;
  7. if (obstacle[j][k] == 0 && j > tempm && j <= tempm + tm-1&&k>tempn&&k<=tempn+tn-1) then
  8. Obstacle[j][k]←1;
  9. end
  10. While 0<j<=m+1&&obstacle[j][1]==0 do
  11. dp[j][1] = 1;
  12. while 0<k<=n+1&&obstacle[1][k]==0 do 
  13. dp[1][k] = 1;
  14. for 1<j<=m+1,1<k<=n+1 do
  15. if (obstacle[j][k] == 0) then dp[j][k]=dp[j-1][k]+dp[j][k-1];
  16. print dp[m+1][n+1];
  17. End

时间复杂度分析:

m, n表示原来的城市垂直和水平方向上有多少个小房子。整数B表示大厦的数量。

初始化obstacle矩阵的时间复杂度是O(B*m*n)

初始化dp二维数组的时间复杂度是O(m+n)

求解dp二维数组的时间复杂度为O(m*n)

所以,总的时间复杂度为O(B*m*n)

4.1.3 手工求解样例

以表格形式展示dp数组,第i行j列的格子中的数字,表示从起点到坐标(i,j)的最短路径数。可推出从起点到右上角终点的最短距离的路径数为192条。

1

6

21

56

91

132

192

1

5

15

35

35

41

60

1

4

10

20

0

6

19

1

3

6

10

0

6

13

1

2

3

4

5

6

7

起点

1

1

1

1

1

1

4.1.4 程序实现

#include<iostream>
#define N 50
typedef struct Building
{
	int bm, bn, mnum, nnum;//大厦左下角坐标,该大厦垂直方向和水平方向占有的房子数
}building;
int m, n;//右上角坐标
int bnum;//大厦数目
int obstacle[N][N]{ 0 };//
int dp[N][N]{0};
using namespace std;
int main()
{
	cout << "input m,n,bnum:";
	cin >> m >> n>>bnum;
	building builds[N]{};
	cout << "输入bnum行:";
	for (int i = 1; i <= bnum; i++)
	{
		cin >> builds[i].bm >> builds[i].bn >> builds[i].mnum >> builds[i].nnum;
	}
	for(int i=1;i<=bnum;i++)
		for (int j = 1; j <= m+1; j++)
			for (int k = 1; k <= n+1; k++)
			{
				int tempm = builds[i].bm, tempn = builds[i].bn;
				int tm = builds[i].mnum, tn = builds[i].nnum;
				if (obstacle[j][k] == 0 && j > tempm && j <= tempm + tm-1&&k>tempn&&k<=tempn+tn-1)
				{
					obstacle[j][k] = 1;
				}
		 }
 
	for (int j = 1; j <= m+1 && obstacle[j][1] == 0; j++) dp[j][1] = 1;
	for (int k = 1; k <= n+1 && obstacle[1][k] == 0; k++) dp[1][k] = 1;
	for (int j = 2; j <= m+1; j++)
		for (int k = 2; k <= n+1; k++)
		{
			if (obstacle[j][k] == 0)
			{
				dp[j][k] = dp[j - 1][k]+dp[j][k-1];
			}
		}
	cout << dp[m+1][n+1];
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guts350

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值