题目链接:

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. leetcode题1Two sum 练习

    题目为: 给一个整数数组, 返回数组中的两数之和等于指定值的两数在数组中的下标. Example: Given nums = [2, 7, 11, 15], target = 9, Because n ...

  2. 未能找到任何适合于指定的区域性或非特定区域性的资源。请确保在编译时已将“xxx.Resources.resources”正确嵌入或链接到程序集

    今天在测试一个工程的时候,突然遇到了这样一个问题: 错误信息:System.Resources.MissingManifestResourceException: 未能找到任何适合于指定的区域或非特定 ...

  3. ubuntu 删除除了某个文件或文件夹之外的所有文件或者目录

    今天需要将网站根目录下的所有文件全部删除但是还需要保留phpmyadmin这个文件夹,本来是可以一个一个删除的,后来想应该会有 一个命令是可以用一个命令删除除了phpmyadmin之外的所有文件和文件 ...

  4. js选中下拉框的默认选项

    //这是修改时选中 $("#type").find("option[value='"+factory+"']").attr("se ...

  5. 杭电ACM2092--整数解

    杭电ACM2092--整数解    分析 http://acm.hdu.edu.cn/showproblem.php?pid=2092 一个YES,一个Yes.试了10几次..我也是无语了..哪里都不 ...

  6. QT 信号与槽连接

    转帖 http://www.cnblogs.com/cnhome/archive/2009/10/01/1577277.html 信号(SIGNAL)和槽(SLOT)是Qt编程的一个重要部分.这个机制 ...

  7. 关于CORS

    前几天碰到CORS问题,只要在“Access-Control-Allow-Origin”响应头中添加对应域名即可. 今天做一个上传文件的demo,利用XMLHttpRequest向服务器发送post请 ...

  8. WindowsPhone8 数据库增删改查

    今天第一次在博客园发表文章,如果有的地方写的不对,还请大家指出! 1.这就是一个简单wp8数据库增删改查 1.创建数据表Person [Table] public class Person : INo ...

  9. SQL Server死锁的分析、处理与预防

    1.基本原理 所谓“死锁”,在操作系统的定义是:在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态. 定义比较抽象,下图可以帮助你比较直观的 ...

  10. mysql颠覆实战笔记(五)--商品系统设计(二):定时更新商品总点击量

    继续回到沈老师的MYSQL颠覆实战,首先回顾下上一节课的内容,请大家会看下上节课写的存储过程. 打开prod_clicklog表, 我们只要把日期(不含时分秒)的部分存在数据库中, 如果同一日期有相同 ...