首页 > 代码库 > CodeForces 677D Vanya and Treasure

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\n",ans);    return 0;}

 

CodeForces 677D Vanya and Treasure