题目链接:

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+分块的更多相关文章

  1. 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 ...

  2. Codeforces Round #355 (Div. 2) D. Vanya and Treasure

    题目大意: 给你一个n × m 的图,有p种宝箱, 每个点上有一个种类为a[ i ][ j ]的宝箱,a[ i ][ j ] 的宝箱里有 a[ i ][ j ] + 1的钥匙,第一种宝箱是没有锁的, ...

  3. 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 ...

  4. 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 ...

  5. 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 ...

  6. 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 ...

  7. Codeforces Round #355 (Div. 2)C - Vanya and Label

    啊啊啊啊啊啊啊,真的是智障了... 这种题目,没有必要纠结来源.只要知道它的结果的导致直接原因?反正这句话就我听的懂吧... ">>"/"&" ...

  8. Codeforces Round #355 (Div. 2) B. Vanya and Food Processor

    菜菜菜!!!这么撒比的模拟题,听厂长在一边比比比了半天,自己想一想,然后纯模拟一下,中间过程检测一下,妥妥的就可以过. 题意:有N个东西要去搞碎,每个东西有一个高度,然后有一台机器支持里面可以达到的最 ...

  9. 水题 Codeforces Round #308 (Div. 2) A. Vanya and Table

    题目传送门 /* 水题:读懂题目就能做 */ #include <cstdio> #include <iostream> #include <algorithm> ...

随机推荐

  1. Android之动态图片

    在Android中,比起静态图片来动态图片会更加生动更加酷炫,因为这种视觉效果,你应该会发现我们手机中大多数应用软件的导航页面也都是采用动态图片来展示.动态图片的格式有gif.png格式等等. 我们就 ...

  2. IOS 模仿TableView封装

    一.先贴一下未封装的代号,好跟后面的对比 @interface MTHomeDropdown : UIView + (instancetype)dropdown; @property (nonatom ...

  3. DTCMS使用ajax局部刷新

    动力启航的DTCMS代码遇到的问题: 前台post请求: $.ajax({ type: "POST", url: sendUrl, dataType: "json&quo ...

  4. Different ways to invoke a shared object/share library(.so)

    在Linux中调用.so文件的方法有几种. 1.直接在编译的时候链接上. 2.dlopen/???

  5. windows phone 8 开发系列(一)环境搭建

    一:前奏说明 本人一名普通的neter,对新玩意有点小兴趣,之前wp7出来的时候,折腾学习过点wp7开发,后来也没怎么用到(主要对微软抛弃wp7的行为比较不爽),现在wp8已经出来一段时间了,市场上也 ...

  6. JS对select动态添加options操作[IE&FireFox兼容]

    <select id="ddlResourceType" onchange="getvalue(this)"> </select> 动态 ...

  7. WindowsMediaPlayer控件批量添加文件至播放列表

    思路: 1.读取批定路径的目录文件. 2.用List存放. 3.循环List列表添加到播放列表. public void VidieoPlay() { //WindowsMediaPlayer1.ui ...

  8. hadoop分布式安装过程

    一.安装准备及环境说明 1.下载hadoop-1.2.1,地址:http://apache.spinellicreations.com/hadoop/common/stable/hadoop-1.2. ...

  9. Android Material Design:滑动指示选项卡android.support.design.widget.TabLayout的简单使用

    该TabLayout的功用,简单的说,就是当用户在该TabLayout的选项卡子item中选择触摸时候,文字和下方的指示器横条滑动指示.这个功能就是以前APP开发常用的选项卡某一卡片被切换.选中时候的 ...

  10. sql2012安装过程中出现个一个问题

    最近安装了一次SQLSERVER2012,遇到了一个小问题,截图如下: 就是上图中状态为失败的项,点开之后,会弹出下面的一个框: 在网上搜了之后,有了这样的答案: http://www.cnblogs ...