题目链接:

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. SVG之初识

    什么是SVG? 也许现在很多人都听说过SVG的人比较多,但不一定了解什么是SVG:SVG(Scalable Vector Graphics 一大串看不懂的英文)可伸缩矢量图形,它是用XML格式来定义用 ...

  2. eBay 开发流程

    1[记录]注册成为eBay开发者(eBay Developers Program)+创建Sanbox Key和Production Key http://www.crifan.com/register ...

  3. C#中调用API

    介绍 API( Application Programming Interface ),我想大家不会陌生,它是我们Windows编程的常客,虽然基于.Net平台的C#有了强大的类库,但是,我们还是不能 ...

  4. 第八篇、封装NSURLSession网络请求框架

    主要功能介绍: 1.GET请求操作 2.POST请求操作 1.处理params参数(例如拼接成:usename="123"&password="123" ...

  5. C语言知识总结(2)

    选择结构-if if(表达式) {} {}为作用域 多重if-else  例如: #include <stdio.h> int main(){ ; ){ printf("没有购物 ...

  6. "Could not load file or assembly 'DTcms.Web.UI' or one of its dependencies. 拒绝访问。" 的解决办法

    出现的问题提示如下:

  7. struts2,hibernate4,spring3配置时问题汇总及解决办法

    文章转载于wanglihu的博客,原文链接http://wanglihu.iteye.com/blog/1897718 1.java.lang.NoClassDefFoundError: org/ob ...

  8. Map排序(按key/按value)

    package com.abc.test; import java.util.ArrayList; import java.util.Arrays; import java.util.Collecti ...

  9. C++ Strings(字符串)

    Constructors 构造函数,用于字符串初始化 Operators 操作符,用于字符串比较和赋值 append() 在字符串的末尾添加文本 assign() 为字符串赋新值 at() 按给定索引 ...

  10. c/c++面试总结(3)

    7.vector和list的区别(这个也算是经常问的) vector和数组类似,拥有一段连续的内存空间,并且起始地址不变,这样对随机的读取很有效率(就是我们所有的[]运算符了),因为内存是连续的如果我 ...