题意:
题目链接:http://codeforces.com/gym/101201/attachments
给出一个迷宫,以及一串上下左右的指令,机器人需要按照指令前进,问最少添加以及删除多少指令可以令机器人顺利从起点走到终点。如果机器人顺着指令遇到障碍或者边界,那么自动忽略这条指令留在原地。
思路:
好题。
dp[i][x][y]表示在前i个指令完成之后,机器人处于(x,y)的最少增加删除代价。
那么dp[i][x][y]可以从dp[i-1][xx][yy]完成第I条指令转移过来,也可以从dp[i][xxx][yyy]完成若干条添加的指令转移过来,这里之所以没考虑删除操作,可以想到添加和删除是等价的,添加一条反向的指令等于删除之前一条正向的指令。
对于同第i个指令之间的影响,采用bfs来对于第i个指令的dp数组进行松弛操作。使得每个状态取得最小值。
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 55;
const int INF = 0x3f3f3f3f;
struct node {
int x, y;
};
const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0, 0, -1, 1};
int n, m;
char mp[MAXN][MAXN];
int dp[MAXN][MAXN][MAXN];
void bfs(int t, int sx, int sy) {
queue <node> que;
que.push((node) {sx, sy});
while (!que.empty()) {
node now = que.front(); que.pop();
int x = now.x, y = now.y;
for (int i = 0; i < 4; i++) {
int nx = x + dx[i], ny = y + dy[i];
if (nx < 1 || nx > n || ny < 1 || ny > m || mp[nx][ny] == '#') continue;
if (dp[t][nx][ny] > dp[t][x][y] + 1) {
dp[t][nx][ny] = dp[t][x][y] + 1;
que.push((node) {nx, ny});
}
}
}
}
char op[MAXN];
int main() {
//freopen("in.txt", "r", stdin);
int sx, sy, ex, ey;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%s", mp[i] + 1);
for (int j = 1; j <= m; j++) {
if (mp[i][j] == 'R') sx = i, sy = j;
else if (mp[i][j] == 'E') ex = i, ey = j;
}
}
scanf("%s", op + 1);
int len = strlen(op + 1);
memset(dp, INF, sizeof(dp));
dp[0][sx][sy] = 0;
for (int i = 0; i <= len; i++) {
for (int x = 1; x <= n; x++) {
for (int y = 1; y <= m; y++) {
bfs(i, x, y);
}
}
/*cout << " ------ " << i << endl;
for (int x = 1; x <= n; x++) {
for (int y = 1; y <= m; y++)
printf("\t%d", dp[i][x][y] == INF ? 999 : dp[i][x][y]);
printf("\n");
}*/
if (i == len) break;
for (int x = 1; x <= n; x++) {
for (int y = 1; y <= m; y++) {
int nx = x, ny = y;
if (op[i + 1] == 'U') nx--;
else if (op[i + 1] == 'D') nx++;
else if (op[i + 1] == 'L') ny--;
else if (op[i + 1] == 'R') ny++;
if (nx < 1 || nx > n || ny < 1 || ny > m || mp[nx][ny] == '#')
nx = x, ny = y;
dp[i + 1][nx][ny] = min(dp[i + 1][nx][ny], dp[i][x][y]);
}
}
}
int ans = INF;
for (int i = 0; i <= len; i++)
ans = min(ans, dp[i][ex][ey]);
printf("%d\n", ans);
return 0;
}