最少拐弯问题——搜索,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;
}