Luo Gu [P2226] [HNOI2001] remote control car race (shortest)

Topic Link
First split points, and each point is split into four points, indicate the time to reach this point the car toward.
Then consider even the edges.
They are adjacent in the same direction and can go right to the point directly connected to the side edge 1.
As for how to turn just at each point \ (i \) has been expanded until it go so far in every direction, if the depth is greater than the sensitivity of the current point, from \ (i \) are the other three directions to this point even one side is the right side of the depth of this point.
Then run \ (SPFA \) (as to why \ (SPFA \) ,I will not tell you is lazy blogger), So you can get \ (90pts \) .
why? As we walked up to \ (10 \) times, and each time the complexity of even the edges are \ (O (n ^ 3) \) level, plus run \ (SPFA \) , it is easy to overtime.
So consider an optimization, it is clear every time even while there are a lot of duplicate place, because the sensitivity is \ (2 \) is certainly the case sensitivity \ (3 \) all sides of the case are connected.
So we might as well turn to run, sensitivity from \ (10 \) to \ (1 \) , the length of a time even just for the sensitivity of the steering side, with a stack record your answers on the line.

\(90pts\)

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#define Open(s) freopen(s".in","r",stdin); freopen(s".out","w",stdout);
#define Close fclose(stdin); fclose(stdout);
#define O(x) cout << #x << "=" << x << endl;
using namespace std;
const int MAXN = 10010 << 2;
const int MAXM = 5000000;
struct Edge{
    int next, to, dis;
}e[MAXM << 1];
int head[MAXN], num, dis[MAXN], vis[MAXN], a[110][110];
inline void Add(int u, int v, int dis){
    e[++num] = (Edge){ head[u], v, dis }; head[u] = num;
}
int n, m, N, l[] = { -1, 1, 0, 0 }, r[] = { 0, 0, -1, 1 }, sx, sy, px, py;
inline int id(int x, int y, int direct){
    return direct * N + (x - 1) * m + y;
}
queue <int> q;
int work(int check){
    num = 0; memset(head, 0, sizeof head);
    memset(dis, 127, sizeof dis);
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j){
            if(!a[i][j]) continue;
            for(int k = 0; k < 4; ++k){
                int x = i + l[k], y = j + r[k];
                if(!a[x][y]) continue;
                Add(id(i, j, k), id(x, y, k), 1);
                for(int o = 1; a[x][y]; x += l[k], y += r[k], ++o)
                    if(o >= check)
                        for(int l = 0; l < 4; ++l)
                            if(l != k)
                                Add(id(i, j, k), id(x, y, l), o);
            }
        }
    dis[id(sx, sy, 0)] = dis[id(sx, sy, 1)] = dis[id(sx, sy, 2)] = dis[id(sx, sy, 3)] = 0;
    vis[id(sx, sy, 0)] = vis[id(sx, sy, 1)] = vis[id(sx, sy, 2)] = vis[id(sx, sy, 3)] = 1;
    q.push(id(sx, sy, 0)); q.push(id(sx, sy, 1)); q.push(id(sx, sy, 2)); q.push(id(sx, sy, 3));
    while(q.size()){
        int u = q.front(); q.pop();
        vis[u] = 0;
        for(int i = head[u]; i; i = e[i].next)
            if(dis[e[i].to] > dis[u] + e[i].dis){
                dis[e[i].to] = dis[u] + e[i].dis;
                if(!vis[e[i].to]){
                    vis[e[i].to] = 1;
                    q.push(e[i].to);
                }
            }
    }
    int ans = min(min(dis[id(px, py, 0)], dis[id(px, py, 1)]), min(dis[id(px, py, 2)], dis[id(px, py, 3)]));
    if(ans < 10000000) return printf("%d %d\n", check, ans), 0;
    else return 1;
}
int main(){
    scanf("%d%d%d%d%d%d", &n, &m, &sx, &sy, &px, &py); N = n * m;
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            scanf("%d", &a[i][j]);
    for(int i = 1; i <= 10; ++i)
        if(work(i))
            break;
    return 0;
}

\(100pts\)

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#define Open(s) freopen(s".in","r",stdin); freopen(s".out","w",stdout);
#define Close fclose(stdin); fclose(stdout);
#define O(x) cout << #x << "=" << x << endl;
using namespace std;
const int MAXN = 10010 << 2;
const int MAXM = 5000000;
struct Edge{
    int next, to, dis;
}e[MAXM << 1];
int head[MAXN], num, dis[MAXN], vis[MAXN], a[110][110], s[12], top;
inline void Add(int u, int v, int dis){
    e[++num] = (Edge){ head[u], v, dis }; head[u] = num;
}
int n, m, N, l[] = { -1, 1, 0, 0 }, r[] = { 0, 0, -1, 1 }, sx, sy, px, py;
inline int id(int x, int y, int direct){
    return direct * N + (x - 1) * m + y;
}
queue <int> q;
void work(int check){
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j){
            if(!a[i][j]) continue;
            for(int k = 0; k < 4; ++k){
                for(int p = 1, x = i + l[k], y = j + r[k]; a[x][y]; ++p, x += l[k], y += r[k])
                    if(p == check){
                        for(int l = 0; l < 4; ++l)
                            if(l != k)
                                Add(id(i, j, k), id(x, y, l), check);
                        break;
                    }
            }
        }
    memset(dis, 127, sizeof dis);
    dis[id(sx, sy, 0)] = dis[id(sx, sy, 1)] = dis[id(sx, sy, 2)] = dis[id(sx, sy, 3)] = 0;
    vis[id(sx, sy, 0)] = vis[id(sx, sy, 1)] = vis[id(sx, sy, 2)] = vis[id(sx, sy, 3)] = 1;
    q.push(id(sx, sy, 0)); q.push(id(sx, sy, 1)); q.push(id(sx, sy, 2)); q.push(id(sx, sy, 3));
    while(q.size()){
        int u = q.front(); q.pop();
        vis[u] = 0;
        for(int i = head[u]; i; i = e[i].next)
            if(dis[e[i].to] > dis[u] + e[i].dis){
                dis[e[i].to] = dis[u] + e[i].dis;
                if(!vis[e[i].to]){
                    vis[e[i].to] = 1;
                    q.push(e[i].to);
                }
            }
    }
    int ans = min(min(dis[id(px, py, 0)], dis[id(px, py, 1)]), min(dis[id(px, py, 2)], dis[id(px, py, 3)]));
    if(ans < 10000000) s[++top] = ans;
}
int main(){
    scanf("%d%d%d%d%d%d", &n, &m, &sx, &sy, &px, &py); N = n * m;
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            scanf("%d", &a[i][j]);
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j){
            if(!a[i][j]) continue;
            for(int k = 0; k < 4; ++k){
                int x = i + l[k], y = j + r[k];
                if(!a[x][y]) continue;
                Add(id(i, j, k), id(x, y, k), 1);
            }
        }
    for(int i = 10; i; --i)
        work(i);
    for(int Top = top, i = 1; i <= Top; ++i)
        printf("%d %d\n", i, s[top--]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/Qihoo360/p/11019262.html