帮XXX规划路线

博客围绕帮XXX规划路线展开,介绍了算法思路,包括标记障碍物、考虑点的转移条件等。通过新数组记录步数,按行处理数据,逐步推导数组状态,最终得出可移动的最大步数,时间复杂度为O(n^2)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

**

帮XXX规划路线

**在这里插入图片描述在这里插入图片描述
在这里插入图片描述
本题的思路如下:
1.该点不能如果不能往下或往右走,那么该点就是一个障碍物,障碍物会阻止其它点经过,所以要对该点进行标记,切断其它点从该点穿过的情况。
2.除了考虑该点能不能去往右点或者下点,还需要考虑该点能否从左点或者上点转过来,所以该点的左点和上点要至少有一个满足没有被标记且该没被标记的点要小于等于该点,否则该点也需要被标记。
3.标记需要用一个新的新数组,新数组中存入-1或者其它数字,-1代表该数据被标记,其余数据记录从该点走到下一个点一共走了几步,最后该数组内的最大值就是可以移动的最大步数。
为了处理边界的问题,我们将题目的数据从第一行第一列开始读取,不然还需要对边界进行单独的判断,比较麻烦。

举例1:
数组1是题目给定的输入,数组2是v数组最后的状态,我们来看看如何一步步得到该数组。
在这里插入图片描述
F[5][5]数组中的内容为:
0 0 0 0 0
0 2 3 4 6
0 7 6 5 3
0 4 5 7 8
0 6 5 8 9
V[5][5]数组初始状态为:
0 0 -1 -1 -1
0 0 0 0 0
-1 0 0 0 0
-1 0 0 0 0
-1 0 0 0 0
因为左上角的点必须要通,所以v数组中不对该点的左方或者上方进行标记。
除了左上角之外的该点之外,第一行和第一列的点需要全部标记,因为f数组中的边缘全是0,不进行标记就会从这些不存在的点通过来。
因为是只能往下或者往右走,所以我们可以从小到大按行处理数据或者从小到大按列处理数据,这里就展示一下按行处理的办法。

第一次:v[0][1] = 0 ;v[1][0] = 0;f[0][1] = 0;f[1][0] = 0;f[1][2] = 3;f[2][1] = 7;
v[0][1]和v[1][0]都不是-1,所以可以从该两点转移过来,且满足(2>=0||2>=0) && (2<=3||2<=7),所以v[1][1]=max(v[0][1],v[1][0])+1 = max(0,0)+1 = 1;
V[5][5]:
0 0 -1 -1 -1
0 1 0 0 0
-1 0 0 0 0
-1 0 0 0 0
-1 0 0 0 0

第二次:因为v[0][2]为-1,所以只能从f[1][1]转移过来,(3>=2)&&(3<=4||3<=6)不成立,所以v[1][2]=v[1][1]+1=2
V[5][5]:
0 0 -1 -1 -1
0 1 2 0 0
-1 0 0 0 0
-1 0 0 0 0
-1 0 0 0 0

第三次:因为v[0][3]为-1,所以只能从f[1][2]转移过来,(6>=4)&&(4<=5||4<=6)成立,所以v[1][3] = v[1][2]+1=3;
V[5][5]:
0 0 -1 -1 -1
0 1 2 3 0
-1 0 0 0 0
-1 0 0 0 0
-1 0 0 0 0

第四次:因为v[0][4]为-1,所以只能从f[1][3]转移过来,(6>=4)&&(6<=0||6<=3)不成立,所以v[1][4] = -1
v[5][5]:
0 0 -1 -1 -1
0 1 2 3 -1
-1 0 0 0 0
-1 0 0 0 0
-1 0 0 0 0

第五次:因为v[2][0] = -1,所以只能从f[1][1]转移过来,(7<=4||7<=6)不成立,所以v[2][1]= -1

第六次:因为v[2][1] = -1,所以只能从f[1][2]转移过来,(6<=5||6<=5)不成立,所以v[2][2] = -1

第七次:因为v[2][2] = -1,所以只能从f[1][3]转移过来,(5>=4)&&(5<=7||5<=3)成立,所以v[2][3] = v[1][3]+1 = 4

第八次:因为V[1][4] = -1,所以只能从f[2][3]转移过来,(3>=5)不成立,所以v[2][4] = -1
v[5][5]:
0 0 -1 -1 -1
0 1 2 3 -1
-1 -1 -1 4 -1
-1 0 0 0 0
-1 0 0 0 0

第九次:因为v[2][1] = -1和v[3][0]都是-1,无法转移,所以v[3][1] = -1

第十次:因为v[2][2] = -1和v[3][1]都是-1,无法转移,所以v[3][2] = -1

第十一次:因为v[3][2] = -1,所以只能从f[2][3]转移过来,(7>=5)&&(7<=8||7<=8)成立,所以v[3][3] = v[2][3]+1 = 5

第十二次:因为v[2][4] = -1,所以只能从f[3][3]转移过来,(8>=7)&&(8<=9||8<=0)成立,所以v[3][4] = v[3][3]+1 = 6
v[5][5]:
0 0 -1 -1 -1
0 1 2 3 -1
-1 -1 -1 4 -1
-1 -1 -1 5 6
-1 0 0 0 0

第十三次:因为v[3][1] = -1和v[4][0]都是-1,无法转移,所以v[4][1] = -1

第十四次:因为v[3][2] = -1和v[4][1]都是-1,无法转移,所以v[4][2] = -1

第十五次:因为v[4][2] = -1,所以只能从f[3][3]转移过来,(8>=7)&&(8<=9||8<=0)成立,所以v[4][3] = v[3][3]+1 =6

第十六次: 9<=0||9<=0不成立,所以v[4][4] = -1
v[5][5]:
0 0 -1 -1 -1
0 1 2 3 -1
-1 -1 -1 4 -1
-1 -1 -1 5 6
-1 -1 -1 6 -1
最后的步数就是该数组中的最大值6,答案与2*n-2相同输出task compete。
时间复杂度O(n^2)

参考AC代码如下:

#include<iostream>
using namespace std;
#define N 1005
int f[N][N] = { 0 };
int v[N][N] = { 0 };

int main()
{
	int n, ans = 0;
	cin >> n;
	for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) cin >> v[i][j];
	for (int i = 2; i <= n; i++) {
		f[0][i] = -1;
		f[i][0] = -1;
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			if (f[i - 1][j] == -1 && f[i][j - 1] == -1)f[i][j] = -1;
			else if (f[i - 1][j] == -1) {
				if (v[i][j] >= v[i][j - 1])f[i][j] = f[i][j - 1] + 1;
				else f[i][j] = -1;
			}
			else if (f[i][j - 1] == -1) {
				if (v[i][j] >= v[i - 1][j])f[i][j] = f[i - 1][j] + 1;
				else f[i][j] = -1;
			}
			else {
				if (v[i][j] >= v[i - 1][j] || v[i][j] >= v[i][j - 1]) f[i][j] = max(f[i][j - 1], f[i - 1][j]) + 1;
				else f[i][j] = -1;
			}
			if (v[i + 1][j] < v[i][j] && v[i][j + 1] < v[i][j])f[i][j] = -1;
		}
	}
	for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) ans = max(ans, f[i][j]);
	if (ans == n * 2 - 2)cout << "Task compete" << endl;
	else cout << ans << endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值