zoukankan      html  css  js  c++  java
  • Codeforces Round #355 (Div. 2) D. Vanya and Treasure dp+分块

    题目链接:

    http://codeforces.com/contest/677/problem/D

    题意:

    让你求最短的从start->...->1->...->2->...->3->...->...->p的最短路径。

    题解:

    这题dp的阶段性还是很明显的,相同的值得方格为同一个阶段,然后求从阶段1->2->3...->p的阶段图最短路。

    初始化所有a[x][y]==1的格子为起始点到(x,y)坐标的距离。

    方程式为dp[x1][y1]=min(dp[x1][y1],dp[x2][y2]+abs(x2-x1)+abs(y2-y1)),其中a[x1][y1]=a[x2][y2]+1。

    但是这要n*n*m*m的复杂度。

    x阶段到x+1阶段的转移数为cnt[x]*cnt[x+1],这个太大,并且多来几个就会爆了,但注意如果cnt[x]*cnt[x+1]大了,其他的如

    cnt[x']*cnt[x'+1]就有可能会变小,因为sum(cnt[i])是固定的,

    那么根据这个特性,我们可以考虑分块!,当cnt[x]*cnt[x+1]<=m*n的时候直接暴力,如果大了就用最短路(spfa就可以)

    这样跑出来的时间复杂度为O(n*m*sqrt(n*m)*log(n*m)),那个log(n*m)是spfa跑出来的。

    具体的均摊时间复杂度证明:http://codeforces.com/blog/entry/45181?#comment-297475

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<utility>
    #include<vector>
    #include<algorithm>
    #include<queue>
    #define mp make_pair
    #define X first
    #define Y second
    using namespace std;
    
    const int maxn = 305;
    
    int dp[maxn][maxn],mat[maxn][maxn];
    int cnt[maxn*maxn],inq[maxn][maxn],d[maxn][maxn];
    vector<pair<int,int> > G[maxn*maxn];
    int n, m, p;
    
    inline int get_dis(int x1, int y1, int x2, int y2) {
        return abs(x1 - x2) + abs(y1 - y2);
    }
    
    const int dx[] = { -1,1,0,0 };
    const int dy[] = { 0,0,-1,1 };
    
    void init() {
        memset(dp, 0x7f, sizeof(dp));
        memset(cnt, 0, sizeof(cnt));
    }
    
    int main() {
        while (scanf("%d%d%d", &n, &m, &p) == 3 && n) {
            init();
            int xt, yt;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    scanf("%d", &mat[i][j]);
                    if (mat[i][j] == 1) dp[i][j] = get_dis(0,0,i,j);
                    if (mat[i][j] == p) xt = i, yt = j;
                    cnt[mat[i][j]]++;
                    G[mat[i][j]].push_back(mp(i, j));
                }
            }
            for (int i = 2; i <= p; i++) {
                if (cnt[i - 1] * cnt[i] <= m*n) {
                    for (int j = 0; j < G[i].size(); j++) {
                        int x2 = G[i][j].X, y2 = G[i][j].Y;
                        for (int k = 0; k < G[i - 1].size(); k++) {
                            int x1 = G[i - 1][k].X, y1 = G[i - 1][k].Y;
                            dp[x2][y2] = min(dp[x2][y2], dp[x1][y1] + get_dis(x1, y1, x2, y2));
                        }
                    }
                }
                else {
                    memset(d, 0x7f, sizeof(d));
                    memset(inq, 0, sizeof(inq));
                    queue<pair<int, int> > Q;
                    for (int j = 0; j < G[i - 1].size(); j++) {
                        pair<int, int> u = G[i - 1][j];
                        d[u.X][u.Y] = dp[u.X][u.Y], inq[u.X][u.Y] = 1;
                        Q.push(mp(u.X, u.Y));
                    }
                    while (!Q.empty()) {
                        pair<int, int> u = Q.front(); Q.pop();
                        inq[u.X][u.Y] = 0;
                        if (mat[u.X][u.Y] == i) dp[u.X][u.Y] = min(dp[u.X][u.Y], d[u.X][u.Y]);
                        for (int j = 0; j < 4; j++) {
                            int x = u.X + dx[j], y = u.Y + dy[j];
                            if (x < 0 || x >= n || y < 0 || y >= m) continue;
                            if (d[x][y] > d[u.X][u.Y] + 1) {
                                d[x][y] = d[u.X][u.Y] + 1;
                                if (!inq[x][y]) inq[x][y] = 1, Q.push(mp(x, y));
                            }
                        }
                    }
                }
            }
            printf("%d
    ", dp[xt][yt]);
        }
        return 0;
    }
  • 相关阅读:
    Android Studio 生成Jar包时遇到的gradlew下载问题
    未解决问题
    Android -- android.os.Parcelable[] cannot be cast to ...
    vulkan gpu limits in mali
    Why GPU Program is expensive in CPU
    iOS native plugin 的代码sample
    USC-- compute shader ps vs
    zprepass 之后再base pass为什么用equal不用lessequal
    memory management Vulkan
    hlslcc
  • 原文地址:https://www.cnblogs.com/fenice/p/5554956.html
Copyright © 2011-2022 走看看