Codeforces 677D - Vanya and Treasure
Posted DarkTong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 677D - Vanya and Treasure相关的知识,希望对你有一定的参考价值。
题意:要走到x、就必须经过x-1,问从(1,1)走到x=p的最短路。
分析:dp[y][x] = min(dp[y][x], dp[ty][tx]+dis((y,x), (ty, tx));
就是从x-1向x递推,不过有可能p=x-1,p=x的点很多,直接来就GG了。
所以就判断,当点数乘积超过n*m就直接bfs去搜,因为bfs所要时间最多是4*n*m, 很客观。吐槽:据说,只要用特殊姿势,就可以不用bfs了。(特殊姿势是有一点概率会错,但概率很小,速度又很快,挺6的)。
#include <bits/stdc++.h> using namespace std; #define INF 0x7f7f7f7f const int maxn = 300+10; int dp[maxn][maxn], vis[maxn][maxn], cnt[maxn*maxn], cn[maxn*maxn]; struct Poi { int x, y, p; Poi(){} Poi(int x, int y, int p):x(x), y(y), p(p){} bool operator<(const Poi &a)const { return p>a.p; } }poi[maxn*maxn]; int dx[]={0,1,0,-1}; int dy[]={1,0,-1,0}; int n, m, p, l; int cmp(const Poi &a, const Poi &b) { return a.p < b.p; } int dis(int a, int b) { return abs(poi[a].x-poi[b].x) + abs(poi[a].y-poi[b].y); } void bfs(int ti) { int x, y; memset(vis, INF, sizeof(vis)); int tcnt=0, len = n*m; queue<Poi> pq; for(int i=cn[ti-1]-cnt[ti-1];i<cn[ti-1];++i) { x=poi[i].x; y=poi[i].y; pq.push(Poi(x, y, dp[y][x])); } while(!pq.empty()) { Poi tp = pq.front(); pq.pop(); for(int i=0;i<4;++i) { int tx=tp.x+dx[i], ty=tp.y+dy[i]; if(ty>=1&&tx>=1&&ty<=n&&tx<=m&&vis[ty][tx]>tp.p+1) { vis[ty][tx]=tp.p+1; tcnt++; pq.push(Poi(tx, ty, tp.p+1)); } } } for(int j=cn[ti-1];j<cn[ti];++j) { x=poi[j].x; y=poi[j].y; dp[y][x] = vis[y][x]; } } int main() { l=0; poi[l++]=Poi(1,1,0); cnt[0]=1; memset(dp, INF, sizeof(dp)); int x, y, tx, ty, i, j, z, t; scanf("%d%d%d", &n, &m, &p); for(i=1;i<=n;++i) for(j=1;j<=m;++j) { scanf("%d", &t); cnt[t]++; poi[l++]=Poi(j, i, t); } sort(poi, poi+l, cmp); cn[0]=1; for(i=1;i<=p;++i) cn[i]=cn[i-1]+cnt[i]; for(i=cn[0];i<cn[1];++i) dp[poi[i].y][poi[i].x]=dis(0,i); for(i=2;i<=p;++i) { if(cnt[i]*cnt[i-1]>=n*m) bfs(i); else { for(j=cn[i-1];j<cn[i];++j) { y=poi[j].y; x=poi[j].x; for(z=cn[i-1]-cnt[i-1];z<cn[i-1];++z) { ty=poi[z].y; tx=poi[z].x; dp[y][x]=min(dp[y][x], dp[ty][tx] + dis(j, z)); } } } } // cout<<"---"<<endl; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) printf("%d%c", dp[i][j], j==m ? ‘\n‘ : ‘ ‘); printf("%d\n", dp[poi[l-1].y][poi[l-1].x]); return 0; }
以上是关于Codeforces 677D - Vanya and Treasure的主要内容,如果未能解决你的问题,请参考以下文章
codeforce 677D Vanya and Treasure
CodeForces - 552C Vanya and Scales
Codeforces 677E - Vanya and Balloons
Codeforces Round #355 (Div. 2) D. Vanya and Treasure 分治暴力