Gym

来源:互联网 发布:绝地游戏画面优化 编辑:程序博客网 时间:2024/06/05 05:13
题意:

给出一张地图和机器人还有出口的位置,地图上面有障碍。然后给出UDLR上下左右四种指令,遇到障碍物或者越界的指令会忽略,剩下的继续执行。

只要到达出口就算找到出口,然后给你一串指令,让你修改指令达到出口,删除或插入任意一个指令花费为1,问让机器人能够找到出口所花费最少。  

思路:

感觉很有意思的一道最短路,思路是把每个点分成变成指令长度个点+1,然后就相当于有n^3个点。然后指令是顺序执行的,所以当前点的状态最多到达

周围可到达点的同一状态。所以我们就可以建边,如果我们走到隔壁点的当前状态就相当于插入了一个指令,就当前点到隔壁点建条花费为1的边。还可以建立

当前点到当前点的下个状态的边,花费为1,相当于删除当前指令。

这道题WA了很久= =然后找到数据对拍,最后发现是因为少建了一种边,就是指令执行完了,然后走向下一个点指令执行完了的边没有建立。

代码:

/** @xigua */#include <cstdio>#include <cmath>#include <iostream>#include <algorithm>#include <vector>#include <stack>#include <cstring>#include <queue>#include <set>#include <string>#include <map>#include <climits>#include <bitset>#define PI acos(-1)using namespace std;typedef long long ll;typedef double db;const int maxn = 2e5 + 5;const int mod = 1e9 + 7;const int INF = 1e8 + 5;const ll inf = 1e15 + 5;const db eps = 1e-6;char mapp[55][55], op[55];int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};int n, m;int cnt, head[maxn], dis[maxn];struct Edge {    int v, w, next;    bool operator < (const Edge &rhs) const {        return w > rhs.w;    }} e[maxn*5];void add(int u, int v, int co) {    e[cnt].v = v;    e[cnt].w = co;    e[cnt].next = head[u];    head[u] = cnt++;}void init() {    cnt = 0;    memset(head, -1, sizeof(head));}void dij(int s, int len) {    priority_queue<Edge> pq;    for (int i = 1; i <= len; i++)        dis[i] = INF;    bool vis[maxn] = {0};    dis[s] = 0;    pq.push((Edge){s, 0});    while (!pq.empty()) {        Edge tmp = pq.top(); pq.pop();        if (vis[tmp.v]) continue;        vis[tmp.v] = 1;        for (int i = head[tmp.v]; ~i; i = e[i].next) {            Edge u = e[i];            if (dis[u.v] > dis[tmp.v] + u.w) {                dis[u.v] = dis[tmp.v] + u.w;                pq.push((Edge){u.v, dis[u.v]});            }        }    }}bool safe(int x, int y) {    return x >= 1 && x <= n && y >= 1 && y <= m && mapp[x][y] != '#';}void solve() {    while (cin >> n >> m) {        init();        for (int i = 1; i <= n; i++)            scanf("%s", mapp[i] + 1);        scanf("%s", op+1);        int len = strlen(op + 1);        int st, ed;        for (int i = 1; i <= n; i++) {            for (int j = 1; j <= m; j++) {                if (mapp[i][j] == 'R') st = (i - 1) * m + j;                if (mapp[i][j] == 'E') ed = (i - 1) * m + j;                if (mapp[i][j] == '#') continue;                for (int k = 1; k <= len; k++) {                    for (int p = 0; p < 4; p++) {                        int x = i + dx[p];                        int y = j + dy[p];                        if (safe(x, y)) {                            int u = ((i - 1) * m + j) * (len + 1) + k;                            int v = ((x - 1) * m + y) * (len + 1) + k;                            add(u, v, 1);                        }                    }                    int x = i, y = j;                    if (op[k] == 'R') y++;                    else if (op[k] == 'L') y--;                    else if (op[k] == 'U') x--;                    else x++;                    if (safe(x, y)) {                        int u = ((i - 1) * m + j) * (len + 1) + k;                        int v = ((x - 1) * m + y) * (len + 1) + k + 1;                        add(u, v, 0);                    }                    else {                        int u = ((i - 1) * m + j) * (len + 1) + k;                        add(u, u + 1, 0);                    }                    int u = ((i - 1) * m + j) * (len + 1) + k;                    add(u, u + 1, 1);                }                /* 就是这里  没有考虑到建立边 */                for (int p = 0; p < 4; p++) {                    int x = i + dx[p];                    int y = j + dy[p];                    if (safe(x, y)) {                        int u = ((i - 1) * m + j) * (len + 1) + len + 1;                        int v = ((x - 1) * m + y) * (len + 1) + len + 1;                        add(u, v, 1);                    }                }            }        }        dij(st * (len + 1) + 1, (n * m + 1) * (len + 1));        int ans = INF;        for (int i = 1; i <= len + 1; i++) {            int cur = ed * (len + 1) + i;            ans = min(ans, dis[cur]);        }        cout << ans << endl;    }}int main() {int t = 1, cas = 1;//freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);//scanf("%d", &t);while (t--) {// printf("Case %d: ", cas++);solve();}return 0;}