最少拐弯问题——搜索,bfs,P1126 机器人搬重物

这几道题对广搜的代码能力提升很会有帮助

P1126 机器人搬重物

题目描述

机器人移动学会(RMI)现在正尝试用机器人搬运物品。机器人的形状是一个直径1.61.6米的球。在试验阶段,机器人被用于在一个储藏室中搬运货物。储藏室是一个 N×M 的网格,有些格子为不可移动的障碍。机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方。机器人接受的指令有:向前移动11步(Creep);向前移动2步(Walk);向前移动33 步(Run);向左转(Left);向右转(Right)。每个指令所需要的时间为11 秒。请你计算一下机器人完成任务所需的最少时间。

输入格式

第一行为两个正整数N,M(N,M≤50),下面N行是储藏室的构造,00表示无障碍,11表示有障碍,数字之间用一个空格隔开。接着一行有44个整数和11个大写字母,分别为起始点和目标点左上角网格的行与列,起始时的面对方向(东E,南S,西W,北N),数与数,数与字母之间均用一个空格隔开。终点的面向方向是任意的。

输出格式

一个整数,表示机器人完成任务所需的最少时间。如果无法到达,输出−1−1。

输入输出样例

输入 #1复制

9 10
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 1 0
7 2 2 7 S

输出 #1复制

12

 

对于最少拐弯问题,其实质上就是最短路径问题:

每向拐一次弯开销就增加一个单位,每走一次也增加一个开销单位,问丛所给起点到所给终点最少的花费是多少。

因此我们可以想到用bfs来解决这道题,大多数最短路径问题也是用bfs来解决的。

但这答题的难点在于题目中细节很多

这道题并不是常见的最短路径问题,不能找直接按平时最短路径的方法做,需要对广搜进行一些改造:广搜中的打擂台。


#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<map>
#include<set>
#include<stack>
#include<queue>

using namespace std;
typedef long long LL;
const int N = 55;
int brr[N][N], arr[N][N], n, m;
typedef struct st {
	int y, x, d, t;
}st;
int ty1, tx1, ty2, tx2, D, ans, f[N][N];
int ay[] = { 0,1,0,-1 }, ax[] = { 1,0,-1,0 };

int fc(int a, int b) {
	int k1, k2;
	k1 = a + 1;
	k2 = a - 1;
	if (k1 > 3)
		k1 = 0;
	if (k2 < 0)
		k2 = 3;
	if (k1 == b || k2 == b) {
		return 0;
	}
	return 1;
}


void bfs() {
	queue<st>q;
	f[ty1][tx1] = 0;
	for (int i = 0; i < 4; i++) {
		for (int j = 1; j <= 3; j++) {
			int ty, tx, t;
			ty = ty1 + ay[i] * j;
			tx = tx1 + ax[i] * j;
			t = 0;
			if (i != D) {
				if (fc(i, D)) {
					t += 1;
				}
				t += 1;
			}
			t += 1;
			if (ty <= 1 || ty > n || tx <= 1 || tx > m)
				continue;
			if (arr[ty][tx] == 1)
				break;
			if (t > f[ty][tx])
				continue;
			f[ty][tx] = t;
			q.push({ ty,tx,i,t });
		}
	}
	st s;
	while (!q.empty()) {
		s = q.front();
		q.pop();
		for (int i = 0; i < 4; i++) {
			for (int j = 1; j <= 3; j++) {
				int ty, tx, t;
				ty = s.y + ay[i] * j;
				tx = s.x + ax[i] * j;

				t = s.t;
				if (i != s.d) {
					if (fc(i, s.d)) {
						t += 1;
					}
					t += 1;
				}
				t += 1;
				if (ty <= 1 || ty > n || tx <= 1 || tx > m)
					continue;
				if (arr[ty][tx] == 1)
					break;
				if (t > f[ty][tx])
					continue;
				f[ty][tx] = t;
				q.push({ ty,tx,i,t });
			}
		}
	}
}



int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			scanf("%d", &brr[i][j]);
		}
	}
	/*
	* 对arr预处理,因为机器人是在格线上走的,所以我们用一个新数组
	*arr来表示机器人 能走的空间
	*/
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (brr[i][j] == 1) {
				arr[i][j] = 1;
				arr[i + 1][j] = 1;
				arr[i][j + 1] = 1;
				arr[i + 1][j + 1] = 1;
			}
		}
	}

	for (int i = 1; i <= n + 1; i++) {
		memset(f[i], 0x3f3f3f3f, sizeof(f[i]));
	}

	scanf("%d%d%d%d", &ty1, &tx1, &ty2, &tx2);
	ty1++;
	ty2++;
	tx1++;
	tx2++;
	char ch; getchar();
	scanf("%c", &ch);
	//将方向转化为数字表示
	if (ch == 'S') {
		D = 1;
	}
	else if (ch == 'E') {
		D = 0;
	}
	else if (ch == 'W') {
		D = 2;
	}
	else {
		D = 3;
	}

	bfs();
	if (f[ty2][tx2] == 0x3f3f3f3f) {
		cout << -1 << endl;
	}
	else {
		cout << f[ty2][tx2] << endl;
	}
	return 0;
}

P2937 [USACO09JAN]Laserphones S

题目描述

The cows have a new laser-based system so they can have casual conversations while out in the pasture which is modeled as a W x H grid of points (1 <= W <= 100; 1 <= H <= 100).

The system requires a sort of line-of-sight connectivity in order to sustain communication. The pasture, of course, has rocks and trees that disrupt the communication but the cows have purchased diagonal mirrors ('/' and '' below) that deflect the laser beam through a 90 degree turn. Below is a map that illustrates the

problem.

H is 8 and W is 7 for this map. The two communicating cows are notated as 'C's; rocks and other blocking elements are notated as '*'s:

7 . . . . . . .         7 . . . . . . . 
6 . . . . . . C         6 . . . . . /-C 
5 . . . . . . *         5 . . . . . | * 
4 * * * * * . *         4 * * * * * | * 
3 . . . . * . .         3 . . . . * | . 
2 . . . . * . .         2 . . . . * | . 
1 . C . . * . .         1 . C . . * | . 
0 . . . . . . .         0 . \-------/ . 
0 1 2 3 4 5 6           0 1 2 3 4 5 6 

Determine the minimum number of mirrors M that must be installed to maintain laser communication between the two cows, a feat which is always possible in the given test data.

奶牛们都改用激光进行通讯了.

在W*H的牧场上,一些地方有树木和石头遮挡激光,所以,奶 牛打算使用对角镜来进行激光通讯.两只奶牛的位置是固定的,对角镜能把光线旋转90度.

输入格式

* Line 1: Two space separated integers: W and H

* Lines 2..H+1: The entire pasture.

输出格式

* Line 1: A single integer: M

题意翻译

输入输出样例

输入 #1复制

7 8 
....... 
......C 
......* 
*****.* 
....*.. 
....*.. 
.C..*.. 
....... 

输出 #1复制

3 

 这道题和上一道题很像,但不能用同样的思路去做,会超时


#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<map>
#include<set>
#include<stack>
#include<queue>

using namespace std;
typedef long long LL;
const int N = 105;
string str[N];
int f[N][N],n,m,y11,x11,y22,x22,h,v[N][N];
typedef struct st {
	int y, x, w, d;
}st;
int ay[] = {0,1,0,-1 }, ax[] = { 1,0,-1,0 };


int fc(int a, int b) {
	int k1 = a + 1;
	int k2 = a - 1;
	if (k1 == b || k2 == b) {
		return 0;
	}
	return 1;
}

void bfs() {
	queue<st>q;
	f[y11][x11] = 0;
	v[y11][x11] = 1;
	for (int i = 0; i < 4; i++) {
		for (int j = 1; j <= h; j++) {
			int ty = y11 + ay[i] * j;
			int tx = x11 + ax[i] * j;
			
			if (ty<1 || ty>n || tx > m || tx < 1||str[ty][tx]=='*')
				break;
			f[ty][tx] = 0;
			v[ty][tx] = 1;
			q.push({ ty,tx,0,i });
		}
	}
	st s;
	while (!q.empty()) {
		s = q.front();
		q.pop();
		for (int i = 0; i < 4; i++) {
			int w;
			w = s.w + 1;
			for (int j = 1; j <= h; j++) {
				int ty = s.y + ay[i] * j;
				int tx = s.x + ax[i] * j;
				if (ty > n || ty < 1 || tx<1 || tx>m || str[ty][tx] == '*' )
					break;
				if ( v[ty][tx]) {
					continue;
				}
				f[ty][tx] = w;
				v[ty][tx] = 1;
				q.push({ ty,tx,w,i });
				if (ty == y22 && tx == x22) {
					return;
				}
			}
		}
	}
}

int main() {
	scanf("%d%d", &m, &n);
	h = max(n, m);
	for (int i = 1; i <= n; i++) {
		cin >> str[i];
		str[i].insert(0, " ");
		for (int j = 1; j <= m; j++) {
			if (str[i][j] == 'C'&&y11==0) {
				y11 = i;
				x11 = j;
			}
			else if (str[i][j] == 'C') {
				y22 = i;
				x22 = j;
			}
		}
		memset(f[i], 0x3f3f3f3f, sizeof(f[i]));
	}

	bfs();


	cout << f[y22][x22] << endl;

	return 0;
}


posted @ 2023-06-18 16:36  Landnig_on_Mars  阅读(7)  评论(0编辑  收藏  举报  来源