CF677D Vanya and Treasure

有一个 \(n\times m\) 的矩阵 \(a(1\le a_{i,j}\le p)\),求从起点 \((1,1)\) 出发依次遍历值为 \(1\to p\) 的矩阵单元的最短路径曼哈顿距离。保证满足 \(a_{i,j}=p\) 的 \((i,j)\) 唯一。

数据范围:\(1\le n,m\le 300\),\(1\le p\le n\cdot m\)。


先记录 \(\tt vector\) 数组 \(w\),\(w_t\) 表示 \(a_{i,j}=t\) 的位置集合。

\(w_t\) 的每个元素有三个属性:\(x,y,g\)。\(x\) 和 \(y\) 是位置坐标,\(g\) 是出发遍历矩阵值 \(1\to t\) 后到 \((x,y)\) 的最短路径长度。


暴力做法:从 \(w_{i-1}\) 的所有 \(g\) 值递推 \(w_i\) 的所有 \(g\) 值:

\[u.g=\min_{v\in w_{i-1}}\{v.g+{\rm abs}(u.x-v.x)+{\rm abs}(u.y-v.y)\}(u\in w_i)
\]

时间复杂度 \(\Theta\left(\sum_{i\in[2,p]}|w_{i-1}|\cdot |w_i|\right)\le\Theta(n^2m^2)\)

  • 怎么卡到 \(\Theta(n^2m^2)\) 的?

比如 \(n=300,m=300,p=2\),矩阵一半是 \(1\) 一半是 \(2\)。


这题的优化是真的巧,反正我比赛时没想到。

考虑以下情况:

\[\forall i\in[2,p]:|w_{i-1}|\cdot|w_i|\le n\cdot m
\]

总的时间复杂度是:

\[\Theta\left(\sum_{i\in[2,p]}|w_{i-1}|\cdot |w_i|\right)
\]

同时满足 \(\sum_{i=1}^p |w_i|=n\cdot m\),根据柯西不等式:

\[\begin{split}
&\left(\sum_{i=2}^p|w_{i-1}|\cdot |w_i|\right)^2\\
\le&\sum_{i=1}^{p-1}|w_i|^2\sum_{i=2}^{p}|w_i|^2\\
\le&\left(\sum_{i=1}^{p}|w_i|^2\right)^2\\
\le&\left(\sqrt{n\cdot m}\times\left(\sqrt{n\cdot m}\right)^2\right)^2
\end{split}
\]

所以 \(\sum_{i=2}^p|w_{i-1}|\cdot |w_i|\le n\cdot m\times\sqrt{n\cdot m}\)。

复杂为 \(\Theta(n\cdot m\sqrt{n\cdot m})\) 可以通过。


但是如果 \(\exists i\in[2,p]:|w_{i-1}|\cdot|w_i|>n\cdot m\) 怎么办呢?

可以套个 \(\Theta(V)\) 的多源无向无权图最短路模板 \(\tt Bfs\)。

所以此时单次递推的时间复杂度也是 \(\Theta(n\cdot m)\)。

这样的单次递推与 \(|w_{i-1}|\cdot|w_i|=n\cdot m\) 相比:

  1. 一次递推时间复杂度相等。

  2. 由于对于这个 \(i\) 的 \(|w_{i-1}|\cdot|w_i|\) 大,所以对于其他 \(i\) 的 \(|w_{i-1}|\cdot|w_i|\) 较小。所以总时间复杂度小。

所以这样优化后总时间复杂度 \(\le \Theta(n\cdot m\sqrt{n\cdot m})\)。可以通过。


  • 代码:
//Data
const int N=3e2;
int n,m,k,a[N+7][N+7];
struct node{
int x,y,g;
node(int X=0,int Y=0,int G=0){x=X,y=Y,g=G;}
};
vector<node> w[N*N+7]; //Bfs
int d[N+7][N+7];
int tx[]={0,0,-1,1},ty[]={-1,1,0,0};
int ok(int x,int y){return 1<=x&&x<=n&&1<=y&&y<=m;}
void Bfs(vector<node>&s){ //多源无向无权图最短路模板 Bfs。
vector<node> q;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) d[i][j]=inf;
int sc=-1;
q.pb(s[++sc]);
for(int i=0;i<sz(q);i++){
node v=q[i];
while(sc+1<sz(s)&&s[sc+1].g<=v.g) q.pb(s[++sc]);
for(int t=0;t<4;t++){
node u=node(v.x+tx[t],v.y+ty[t]);
if(ok(u.x,u.y)&&v.g+1<d[u.x][u.y]) d[u.x][u.y]=u.g=v.g+1,q.pb(u);
}
}
} //Main
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
if(a[i][j]==1) w[a[i][j]].pb(node(i,j,i+j-2));
else w[a[i][j]].pb(node(i,j,inf));
}
for(int key=2;key<=k;key++){
if(sz(w[key-1])*sz(w[key])<=n*m){
for(node&u:w[key]) for(node v:w[key-1])
u.g=min(u.g,v.g+abs(u.x-v.x)+abs(u.y-v.y));
} else {
vector<node> s;
for(node v:w[key-1]) s.pb(v);
Bfs(s);
for(node&u:w[key]) u.g=d[u.x][u.y];
}
}
printf("%d\n",w[k][0].g);
return 0;
}

祝大家学习愉快!

题解-CF677D Vanya and Treasure的更多相关文章

  1. codeforces 677D D. Vanya and Treasure(二维线段树)

    题目链接: D. Vanya and Treasure time limit per test 1.5 seconds memory limit per test 256 megabytes inpu ...

  2. Codeforces Round #355 (Div. 2) D. Vanya and Treasure 分治暴力

    D. Vanya and Treasure 题目连接: http://www.codeforces.com/contest/677/problem/D Description Vanya is in ...

  3. Codeforces 677D Vanya and Treasure 暴力+BFS

    链接 Codeforces 677D Vanya and Treasure 题意 n*m中有p个type,经过了任意一个 type=i 的各自才能打开 type=i+1 的钥匙,最初有type=1的钥 ...

  4. CodeForces 677D. Vanya and Treasure 枚举行列

    677D. Vanya and Treasure 题意: 给定一张n*m的图,图上每个点标有1~p的值,你初始在(1,1)点,你必须按照V:1,2,3...p的顺序走图上的点,问你如何走时间最少. 思 ...

  5. 【12.78%】【codeforces 677D】Vanya and Treasure

    time limit per test1.5 seconds memory limit per test256 megabytes inputstandard input outputstandard ...

  6. 题解 CF492C Vanya and Exams

    CF492C Vanya and Exams 有了Pascal题解,来一波C++题解呀qwq.. 简单的贪心题 按b[i]从小到大排序,一个一个学科写直到达到要求即可 #include<cstd ...

  7. Codeforces Round #355 (Div. 2) D. Vanya and Treasure dp+分块

    题目链接: http://codeforces.com/contest/677/problem/D 题意: 让你求最短的从start->...->1->...->2->. ...

  8. Codeforces 677D - Vanya and Treasure - [DP+优先队列BFS]

    题目链接:http://codeforces.com/problemset/problem/677/D 题意: 有 $n \times m$ 的网格,每个网格上有一个棋子,棋子种类为 $t[i][j] ...

  9. CodeForces 677D Vanya and Treasure

    $dp$,树状数组. 很明显这是一个$DAG$上的$dp$,由于边太多,暴力$dp$会超时,需要优化. 例如计算$dp[x][y]$,可以将区域分成四块,$dp[x][y]$取四块中的最小值,每一块用 ...

随机推荐

  1. 使用GitHub API上传文件及GitHub做图床

    本文介绍GitHub API基础及上传文件到仓库API,并应用API将GitHub作为图床 GitHub API官方页面 GitHub API版本 当前版本为v3,官方推荐在请求头中显示添加版本标识. ...

  2. EF Core 一、重识 EF

    重识EF EF Core 学习资料:https://docs.microsoft.com/zh-cn/ef/core/dbcontext-configuration/ 本为作为EF Core学习的开始 ...

  3. http服务器文件名大小写忽略

    问题 文件从windows里面放到nginx里面去的时候,文件在windows下面是大小写忽略,也就是不论大小写都可以匹配的,而到linux下面的时候,因为linux是区分大小写的,也就是会出现无法忽 ...

  4. EF Core 二 、 入门 EF Core

    入门EF Core 我们将开始真正的EF之旅了,这里使用SqlServer数据,然后DbFirst: 为嘛使用SqlServer,目前公司的整体业务全部在SqlSever,所以很多产品业务都是依托于这 ...

  5. 玩转 Comparator 和 Comparable 两接口

    最近项目中有排序的需求,就查看了一下Java文档,发现有两个接口都可以进行排序,Comparable 和 Comparator 两接口到底有啥区别?何时用?怎么用?使用场景我都在底下一一研究分享出来: ...

  6. abp(net core)+easyui+efcore实现仓储管理系统——出库管理之六(五十五)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统--ABP总体介绍(一) abp(net core)+ ...

  7. 云服务器-Ubuntu更新系统版本-更新Linux内核-服务器安全配置优化-防反弹shell

    购入了一台阿里云的ESC服务器,以前都用CentOS感觉Yum不怎么方便,这次选的Ubuntu16.04.7 搭好服务之后做安全检查,发现Ubuntu16.04版本漏洞众多:虽然也没有涉及到16.04 ...

  8. 面试大厂,90%会被问到的Java面试题(附答案)

    面向对象的三个特征 封装,继承,多态 多态的好处,代码中如何实现多态,虚拟机中如何实现多态 允许不同类对象对同一消息作出相应,好处如下: 可替换性:多态对已存在的代码具有可替换性 可扩充性:增加新的子 ...

  9. ABBYY FineReader 15 新增编辑表格单元格功能

    ABBYY FineReader 15(Windows系统)新增编辑表格单元格功能,在PDF文档存在表格的前提下,可将表中的每个单元格作为单独的文字块进行单独编辑,单元格内的编辑不会影响同一行中其他单 ...

  10. 通俗解析莱文斯坦距离(Levenshtein Distance)计算原理(最小编辑距离)

    [版权声明]:本文章由danvid发布于http://danvid.cnblogs.com/,如需转载或部分使用请注明出处 最近看到一些动态规划的东西讲到莱文斯坦距离(编辑距离)的计算,发现很多都讲的 ...