Gym 101201B dp

题意:

题目链接: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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值