Codeforces Round #355 (Div. 2) D. Vanya and Treasure dp+分块
题目链接:
http://codeforces.com/contest/677/problem/D
题意:
让你求最短的从start->...->1->...->2->...->3->...->...->p的最短路径。
题解:
这题dp的阶段性还是很明显的,相同的值得方格为同一个阶段,然后求从阶段1->2->3...->p的阶段图最短路。
初始化所有a[x][y]==1的格子为起始点到(x,y)坐标的距离。
方程式为dp[x1][y1]=min(dp[x1][y1],dp[x2][y2]+abs(x2-x1)+abs(y2-y1)),其中a[x1][y1]=a[x2][y2]+1。
但是这要n*n*m*m的复杂度。
x阶段到x+1阶段的转移数为cnt[x]*cnt[x+1],这个太大,并且多来几个就会爆了,但注意如果cnt[x]*cnt[x+1]大了,其他的如
cnt[x']*cnt[x'+1]就有可能会变小,因为sum(cnt[i])是固定的,
那么根据这个特性,我们可以考虑分块!,当cnt[x]*cnt[x+1]<=m*n的时候直接暴力,如果大了就用最短路(spfa就可以)
这样跑出来的时间复杂度为O(n*m*sqrt(n*m)*log(n*m)),那个log(n*m)是spfa跑出来的。
具体的均摊时间复杂度证明:http://codeforces.com/blog/entry/45181?#comment-297475
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<utility>
#include<vector>
#include<algorithm>
#include<queue>
#define mp make_pair
#define X first
#define Y second
using namespace std; const int maxn = ; int dp[maxn][maxn],mat[maxn][maxn];
int cnt[maxn*maxn],inq[maxn][maxn],d[maxn][maxn];
vector<pair<int,int> > G[maxn*maxn];
int n, m, p; inline int get_dis(int x1, int y1, int x2, int y2) {
return abs(x1 - x2) + abs(y1 - y2);
} const int dx[] = { -,,, };
const int dy[] = { ,,-, }; void init() {
memset(dp, 0x7f, sizeof(dp));
memset(cnt, , sizeof(cnt));
} int main() {
while (scanf("%d%d%d", &n, &m, &p) == && n) {
init();
int xt, yt;
for (int i = ; i < n; i++) {
for (int j = ; j < m; j++) {
scanf("%d", &mat[i][j]);
if (mat[i][j] == ) dp[i][j] = get_dis(,,i,j);
if (mat[i][j] == p) xt = i, yt = j;
cnt[mat[i][j]]++;
G[mat[i][j]].push_back(mp(i, j));
}
}
for (int i = ; i <= p; i++) {
if (cnt[i - ] * cnt[i] <= m*n) {
for (int j = ; j < G[i].size(); j++) {
int x2 = G[i][j].X, y2 = G[i][j].Y;
for (int k = ; k < G[i - ].size(); k++) {
int x1 = G[i - ][k].X, y1 = G[i - ][k].Y;
dp[x2][y2] = min(dp[x2][y2], dp[x1][y1] + get_dis(x1, y1, x2, y2));
}
}
}
else {
memset(d, 0x7f, sizeof(d));
memset(inq, , sizeof(inq));
queue<pair<int, int> > Q;
for (int j = ; j < G[i - ].size(); j++) {
pair<int, int> u = G[i - ][j];
d[u.X][u.Y] = dp[u.X][u.Y], inq[u.X][u.Y] = ;
Q.push(mp(u.X, u.Y));
}
while (!Q.empty()) {
pair<int, int> u = Q.front(); Q.pop();
inq[u.X][u.Y] = ;
if (mat[u.X][u.Y] == i) dp[u.X][u.Y] = min(dp[u.X][u.Y], d[u.X][u.Y]);
for (int j = ; j < ; j++) {
int x = u.X + dx[j], y = u.Y + dy[j];
if (x < || x >= n || y < || y >= m) continue;
if (d[x][y] > d[u.X][u.Y] + ) {
d[x][y] = d[u.X][u.Y] + ;
if (!inq[x][y]) inq[x][y] = , Q.push(mp(x, y));
}
}
}
}
}
printf("%d\n", dp[xt][yt]);
}
return ;
}
Codeforces Round #355 (Div. 2) D. Vanya and Treasure dp+分块的更多相关文章
- 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 ...
- Codeforces Round #355 (Div. 2) D. Vanya and Treasure
题目大意: 给你一个n × m 的图,有p种宝箱, 每个点上有一个种类为a[ i ][ j ]的宝箱,a[ i ][ j ] 的宝箱里有 a[ i ][ j ] + 1的钥匙,第一种宝箱是没有锁的, ...
- Codeforces Round #355 (Div. 2) C. Vanya and Label 水题
C. Vanya and Label 题目连接: http://www.codeforces.com/contest/677/problem/C Description While walking d ...
- Codeforces Round #355 (Div. 2) B. Vanya and Food Processor 水题
B. Vanya and Food Processor 题目连接: http://www.codeforces.com/contest/677/problem/B Description Vanya ...
- Codeforces Round #355 (Div. 2) A. Vanya and Fence 水题
A. Vanya and Fence 题目连接: http://www.codeforces.com/contest/677/problem/A Description Vanya and his f ...
- Codeforces Round #355 (Div. 2)-B. Vanya and Food Processor,纯考思路~~
B. Vanya and Food Processor time limit per test 1 second memory limit per test 256 megabytes input s ...
- Codeforces Round #355 (Div. 2)C - Vanya and Label
啊啊啊啊啊啊啊,真的是智障了... 这种题目,没有必要纠结来源.只要知道它的结果的导致直接原因?反正这句话就我听的懂吧... ">>"/"&" ...
- Codeforces Round #355 (Div. 2) B. Vanya and Food Processor
菜菜菜!!!这么撒比的模拟题,听厂长在一边比比比了半天,自己想一想,然后纯模拟一下,中间过程检测一下,妥妥的就可以过. 题意:有N个东西要去搞碎,每个东西有一个高度,然后有一台机器支持里面可以达到的最 ...
- 水题 Codeforces Round #308 (Div. 2) A. Vanya and Table
题目传送门 /* 水题:读懂题目就能做 */ #include <cstdio> #include <iostream> #include <algorithm> ...
随机推荐
- GitHub之上传文件
github是一个基于git的代码托管平台,付费用户可以建私人仓库,我们一般的免费用户只能使用公共仓库,也就是代码要公开.对于一般人来说公共仓库就已经足够了,而且我们也没多少代码来管理,O(∩_∩)O ...
- asp连接SQL数据库的代码
connstr="driver={SQL Server};server=(local);uid=sa;pwd=sa;database=Your database" 语法介绍: 1. ...
- 【转载】php程序员:从1.5K到18K 一个程序员的5年成长之路
昨天收到了心仪企业的口头offer, 回首当初什么都不会开始学编程, 到现在恰好五年. 整天在社区晃悠, 看了不少的总结, 在这个时间点, 我也写一份自己的总结吧. 我一直在社区分享, 所以, 这篇总 ...
- iOS - UIView操作(SWift)
1. UIView 视图的渐变填充 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after ...
- 10款免费CSS编辑器应对于Linux和Ubuntu
您是否在使用Linux和Ubuntu的,不知道在哪里可以找到一些优秀且免费的CSS编辑器用于Linux和Ubuntu的?如果你的答案是肯定的,然后停止幻想,开始浏览这个帖子里,我们展示了前10名,并免 ...
- 杭电ACM2076--夹角有多大(题目已修改,注意读题)
杭电ACM2076--夹角有多大(题目已修改,注意读题) http://acm.hdu.edu.cn/showproblem.php?pid=2076 思路很简单.直接贴代码.过程分析有点耗时间. / ...
- 杭电ACM2092--整数解
杭电ACM2092--整数解 分析 http://acm.hdu.edu.cn/showproblem.php?pid=2092 一个YES,一个Yes.试了10几次..我也是无语了..哪里都不 ...
- C++向main函数传递参数的方法(实例已上传至github)
通常情况下,我们定义的main函数都只有空形参列表: int main(){...} 然而,有时我们确实需要给mian传递实参,一种常见的情况是用户设置一组选项来确定函数所要执行的操作.例如,假定ma ...
- 初步了解SequoiaDB数据库
随着企业中日益复杂与多变的需求,以及迅速扩展带来的海量数据的业务,IT部门需要将越来越多的信息提供给用户,同时在现今的全球经济背景环境下,IT部 门还需要在提供高效服务的同时,降低其设备与程序维护成本 ...
- 三种找回 linux root密码的方法
找回 linux root密码的三种方法 第1种方法: 1.在系统进入单用户状态,直接用passwd root去更改2.用安装光盘引导系统,进行linux rescue状态,将原来/分区挂接上来,作法 ...