首页 > 代码库 > 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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。