codeforces 677D

题解:

这东西就是分层DP

考虑dp ( i , j )表示到位置( i , j )的最短长度

然后可以枚举上一次的位置转移过来

这样单次转移复杂度和两层中点的数量有关

这样复杂度显然是O((nm)^2)的,爆炸

考虑另一种暴力,每次转移时bfs,这样单次转移复杂度O(nm)

考虑根号分治,当两层点数乘积>nm时用bfs,这种情况不会超过sqrt(nm)个

然后两层点数乘积<nm时,考虑暴力DP转移

复杂度O(nmsqrt(nm))

  1 #include<bits/stdc++.h>
  2 #define maxn 305
  3 #define pii pair<int,int>
  4 #define mp(a,b) make_pair(a,b)
  5 using namespace std;
  6 int n,m,p;
  7 vector<pii> v[maxn*maxn];
  8 struct node
  9 {
 10     pii pos;
 11     int dis;
 12     node(){}
 13     node(pii P,int D){pos=P;dis=D;}
 14 };
 15 bool operator < (node a,node b)
 16 {
 17     return a.dis<b.dis;
 18 }
 19 int ans[maxn][maxn],dis[maxn][maxn];
 20 bool vis[maxn][maxn];
 21 int Ax,Ay;
 22 int main()
 23 {
 24     scanf("%d%d%d",&n,&m,&p);
 25     for(int i=1;i<=n;++i)
 26         for(int j=1;j<=m;++j)
 27         {
 28             int x;
 29             scanf("%d",&x);
 30             v[x].push_back(mp(i,j));
 31             if(x==p)Ax=i,Ay=j;
 32         }
 33     memset(ans,127/2,sizeof(ans));
 34     for(int i=0;i<v[1].size();++i)
 35     {
 36         int x=v[1][i].first,y=v[1][i].second;
 37         ans[x][y]=abs(x-1)+abs(y-1);
 38     }
 39     for(int i=2;i<=p;++i)
 40     {
 41         if(v[i-1].size()*v[i].size()<n*m)
 42         {
 43             for(int j=0;j<v[i].size();++j)
 44             {
 45                 for(int k=0;k<v[i-1].size();++k)
 46                 {
 47                     int x=v[i][j].first,y=v[i][j].second;
 48                     int u=v[i-1][k].first,w=v[i-1][k].second;
 49                     ans[x][y]=min(ans[x][y],ans[u][w]+abs(x-u)+abs(y-w));
 50                 }
 51             }
 52         }
 53         else
 54         {
 55             const int dx[]={-1,0,1,0};
 56             const int dy[]={0,-1,0,1};
 57             memset(dis,0,sizeof(dis));
 58             memset(vis,0,sizeof(vis));
 59             vector<node> t;
 60             queue<node> q1,q2;
 61             for(int j=0;j<v[i-1].size();++j)t.push_back(node(v[i-1][j],ans[v[i-1][j].first][v[i-1][j].second]));
 62             sort(t.begin(),t.end());
 63             for(int j=0;j<t.size();++j)
 64             {
 65                 q2.push(t[j]);
 66                 int x=t[j].pos.first,y=t[j].pos.second;
 67                 vis[x][y]=1;
 68                 dis[x][y]=t[j].dis;
 69             }
 70             while(!q1.empty()||!q2.empty())
 71             {
 72                 node u;
 73                 if(q1.empty())u=q2.front(),q2.pop();
 74                 else if(q2.empty())u=q1.front(),q1.pop();
 75                 else
 76                 {
 77                     if(q1.front().dis<q2.front().dis)u=q1.front(),q1.pop();
 78                     else u=q2.front(),q2.pop();
 79                 }
 80                 int x=u.pos.first,y=u.pos.second;
 81                 for(int k=0;k<4;++k)
 82                 {
 83                     int nx=x+dx[k],ny=y+dy[k],nd=u.dis+1;
 84                     if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&(!vis[nx][ny]))
 85                     {
 86                         vis[nx][ny]=1;
 87                         dis[nx][ny]=nd;
 88                         q1.push(node(mp(nx,ny),nd));
 89                     }
 90                 }
 91             }
 92             for(int j=0;j<v[i].size();++j)
 93             {
 94                 int x=v[i][j].first,y=v[i][j].second;
 95                 ans[x][y]=dis[x][y]; 
 96             } 
 97         }
 98     }
 99     printf("%d\n",ans[Ax][Ay]);
100     return 0;
101 }
View Code

猜你喜欢

转载自www.cnblogs.com/uuzlove/p/10548587.html
今日推荐