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;
    }
  • 相关阅读:
    写一些,给2013
    C# DateTime变量不能赋null值
    31222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
    王爽《汇编语言》第三版 第十五章 外中断
    王爽《汇编语言》第三版 第十四章 端口
    王爽《汇编语言》第三版 第十二章 内中断
    王爽《汇编语言》第三版 第十一章 标志寄存器
    王爽《汇编语言》第三版 第十章 call和ret指令
    王爽《汇编语言》第三版 第九章 转移指令的原理
    王爽《汇编语言》第三版 第八章 数据处理的两个基本问题
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5869621.html
Copyright © 2011-2022 走看看