zoukankan      html  css  js  c++  java
  • CodeForces 677D Vanya and Treasure

    $dp$,树状数组。

    很明显这是一个$DAG$上的$dp$,由于边太多,暴力$dp$会超时,需要优化。

    例如计算$dp[x][y]$,可以将区域分成四块,$dp[x][y]$取四块中的最小值,每一块用一个二维树状数组维护最小值即可。

    每次扩展一层需要一个新的树状数组,因为每次初始化树状数组会超时,所以可以额外开一个数组记录一下每一个点是第几次更新的。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-6;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    template <class T>
    inline void read(T &x)
    {
        char c=getchar(); x=0;
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) {x=x*10+c-'0'; c=getchar();}
    }
    
    const int INF=0x7FFFFFFF;
    const int maxn=310;
    int n,m,p,a[maxn][maxn],c[4][maxn][maxn],d[4][maxn][maxn],dp[maxn][maxn];
    vector<int>v[maxn*maxn];
    
    int lowbit(int x){return x&(-x);}
    
    int get(int op,int h,int x,int y)
    {
        int res=INF;
        for(int i=x;i>0;i=i-lowbit(i))
            for(int j=y;j>0;j=j-lowbit(j))
                if(d[op][i][j]==h) res=min(res,c[op][i][j]);
        return res;
    }
    
    void update(int op,int h,int x,int y,int v)
    {
        for(int i=x;i<=n;i=i+lowbit(i))
            for(int j=y;j<=m;j=j+lowbit(j))
            {
                if(d[op][i][j]!=h) c[op][i][j]=INF;
                d[op][i][j]=h; c[op][i][j]=min(c[op][i][j],v);
            }
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&p);
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++) 
            {
                scanf("%d",&a[i][j]);
                v[a[i][j]].push_back(i*m+j);
            }
        
        for(int k=0;k<4;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    c[k][i][j]=INF,d[k][i][k]=-100;
                    
        for(int i=0;i<v[1].size();i++) 
            dp[v[1][i]/m+1][(v[1][i]%m)+1]=v[1][i]/m+v[1][i]%m;
    
        for(int i=2;i<=p;i++)
        {
            for(int j=0;j<v[i-1].size();j++)
            {
                int r=v[i-1][j]/m,c=v[i-1][j]%m; r++; c++;
                update(0,i-1,r,c,dp[r][c]-r-c);
                update(1,i-1,r,m-c+1,dp[r][c]-r+c);
                update(2,i-1,n-r+1,c,dp[r][c]+r-c);
                update(3,i-1,n-r+1,m-c+1,dp[r][c]+r+c);
            }
    
            for(int j=0;j<v[i].size();j++)
            {
                int r=v[i][j]/m,c=v[i][j]%m; r++; c++; dp[r][c]=INF;
                if(get(0,i-1,r,c)!=INF) dp[r][c]=min(dp[r][c],get(0,i-1,r,c)+r+c);
                if(get(1,i-1,r,m-c+1)!=INF) dp[r][c]=min(dp[r][c],get(1,i-1,r,m-c+1)+r-c);
                if(get(2,i-1,n-r+1,c)!=INF) dp[r][c]=min(dp[r][c],get(2,i-1,n-r+1,c)-r+c);
                if(get(3,i-1,n-r+1,m-c+1)!=INF) dp[r][c]=min(dp[r][c],get(3,i-1,n-r+1,m-c+1)-r-c);
            }
        }
    
        int ans=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                if(a[i][j]==p) ans=dp[i+1][j+1];
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    测试rar/bz2/tar.gz/gz压缩文档完整性
    php中ajax调用出错的问题
    WIN32_LEAN_AND_MEAN宏
    Windows XP SP3下编译安装check-0.10.0
    Windows XP SP3下成功编译CUint2.1-3
    WebService客户端调用的几种方式
    Webservice 返回数据集 DataSet 及Android显示数据集LiveBindings
    REST 服务器调试 RESTDebugger.exe 和浏览器测试 webservice 调试工具
    delphi android路径 TPath 文件路径,文件管理 file path
    RESTClient 控件 从服务器获得数据集 REST
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5869621.html
Copyright © 2011-2022 走看看