http://codeforces.com/problemset/problem/677/D

题目大意:

给你一个n*m的图,上面有p种钥匙(p<=n*m),每种钥匙至少有一个,期初所有为1的钥匙都是可拿的,拿到了该钥匙以后(假设该钥匙的val是v)就可以拿v+1种类的钥匙。问最后拿到第p个钥匙最少走多少步?(钥匙为p种类的只有一种)

思路:官方题解貌似是二维线段树的,不过这题可以用另外一个方法来优化。

首先假设我们目前在的颜色的c,我们要到c+1颜色的格子里面去,如果单纯的对于每种颜色c跑一次spfa的话,那么就是n*n*m*m了,所以我们分类讨论。当len(c)*len(c+1)<=n*m的时候,直接暴力就好了,反之就跑spfa。因为len(c)*len(c+1)的组数必然不多,所以肯定比每次直接跑n*m的spfa要好。

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
const int inf = 0x3f3f3f3f;
const int maxn = + ;
int n, m, p;
int atlas[maxn][maxn];
vector<pair<int, int> > v[maxn * maxn];
int dp[maxn][maxn], dis[maxn][maxn];
bool vis[maxn][maxn];
int dx[] = {-, , , };
int dy[] = {, , , -}; int solve(){
for (int i = ; i < p; i++){
int len1 = v[i].size();
int len2 = v[i + ].size();
if (len1 * len2 <= n * m){
for (int j = ; j < len1; j++){
int jx = v[i][j].fi, jy = v[i][j].se;
for (int k = ; k < len2; k++){
int kx = v[i + ][k].fi, ky = v[i + ][k].se;
dp[kx][ky] = min(dp[kx][ky], dp[jx][jy] + abs(kx - jx) + abs(ky - jy));
}
}
}
else {
memset(dis, -, sizeof(dis));
memset(vis, false, sizeof(vis));
queue<pair<int, int> > que;
for (int j = ; j < len1; j++){
int jx = v[i][j].fi, jy = v[i][j].se;
dis[jx][jy] = dp[jx][jy];
que.push(mk(jx, jy));
vis[jx][jy] = true;
}
while (!que.empty()){
pair<int, int> u = que.front(); que.pop();
vis[u.fi][u.se] = false;
for (int j = ; j < ; j++){
int jx = u.fi + dx[j], jy = u.se + dy[j];
if (jx <= || jx > n || jy <= || jy > m) continue;
if (dis[jx][jy] == - || dis[jx][jy] > dis[u.fi][u.se] + ){
dis[jx][jy] = dis[u.fi][u.se] + ;
if (!vis[jx][jy]){
vis[jx][jy] = true;
que.push(mk(jx, jy));
}
}
}
}
for (int j = ; j < len2; j++){
int jx = v[i + ][j].fi, jy = v[i + ][j].se;
dp[jx][jy] = min(dp[jx][jy], dis[jx][jy]);
}
}
}
int px = v[p][].fi, py = v[p][].se;
return dp[px][py];
} int main(){
cin >> n >> m >> p;
for (int i = ; i <= n; i++){
for (int j = ; j <= m; j++){
int c; scanf("%d", &c);
if (c == ) dp[i][j] = i + j - ;
else dp[i][j] = inf;
v[c].pb(mk(i, j));
atlas[i][j] = c;
}
}
printf("%d\n", solve());
return ;
}

codeforces div2 677 D的更多相关文章

  1. Codeforces Round #677 (Div. 3) 题解

    Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...

  2. codeforces DIV2 D 最短路

    http://codeforces.com/contest/716/problem/D 题目大意:给你一些边,有权值,权值为0的表示目前该边不存在,但是可以把0修改成另外一个权值.现在,我们重新建路, ...

  3. codeforces div2.C

    C. New Year and Rating time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  4. codeforces div2 603 D. Secret Passwords(并查集)

    题目链接:https://codeforces.com/contest/1263/problem/D 题意:有n个小写字符串代表n个密码,加入存在两个密码有共同的字母,那么说这两个密码可以认为是同一个 ...

  5. codeforces div2 603 E. Editor(线段树)

    题目链接:https://codeforces.com/contest/1263/problem/E 题意:一个编译器,每次输入一些字符,R表示光标右移,L表示光标左移,然后有一些左括号(  和 右括 ...

  6. codeforces div2 603 C. Everyone is a Winner!(二分)

    题目链接:https://codeforces.com/contest/1263/problem/C 题意:给你一个数字n,求n/k有多少个不同的数 思路:首先K大于n时,n/k是0.然后k取值在1到 ...

  7. Codeforces Round #677 (Div. 3) D/1433D Districts Connection

    https://codeforces.com/contest/1433/problem/D 找两个不同权值的节点A.B连起来,所有与A不同权值的连到A上,相同的连到B上. #include<io ...

  8. Codeforces Round #677 (Div. 3) G. Reducing Delivery Cost(dijkstra算法)

    题目链接:https://codeforces.com/contest/1433/problem/G 题解 跑 \(n\) 遍 \(dijkstra\) 得到任意两点间的距离,然后枚举哪一条边权为 \ ...

  9. Codeforces Round #677 (Div. 3)【ABCDE】

    比赛链接:https://codeforces.com/contest/1433 A. Boring Apartments 题解 模拟即可. 代码 #include <bits/stdc++.h ...

随机推荐

  1. ios 测试工程是否内存泄漏

    转自http://www.cocoachina.com/ios/20141203/10519.html 虽然iOS 5.0版本之后加入了ARC机制,由于相互引用关系比较复杂时,内存泄露还是可能存在.所 ...

  2. hibernate在配置文件中配置对象关系映射文件即hbm文件路径的写法

    hbm文件如果在src下,则<mapping resource="*.hbm.xml"/> 如果在实体类包中,则<mapping resource="c ...

  3. unity Mesh(网格)的使用

    创建两个三角形合成的矩形网格: GameObject obj= new GameObject(); MeshRenderer meshRenderer=obj.AddComponent<Mesh ...

  4. OA系统出现窗口拦截的解决办法

    我们使用oa时候,有时候会出现“你打开了窗口拦截功能”.如图 出现窗口被拦截主要有三种情况,分别是IE浏览器本身拦截功能.第三方插件(如百度工具栏.搜搜工具栏.谷歌工具栏等).第三方浏览器拦截功能(如 ...

  5. restlet上传图片代码

    客户端用的是 jquery file upload, 服务器端用的是restlet package org.soachina.rest.component.resource; import java. ...

  6. MySQL 的实时性能监控利器【转】

    操作系统及MySQL数据库的实时性能状态数据尤为重要,特别是在有性能抖动的时候,这些实时的性能数据可以快速帮助你定位系统或MySQL数据库的性能瓶颈,就像你在Linux系统上使用「top,sar,io ...

  7. 取distinct数据同时还取其他字段

    的 SELECT id,group_concat(distinct model) FROM tsdr_case group by model order by id

  8. Eclipse 安装最新SVN插件

    本文来源:http://liujianqiao398.blog.163.com/blog/static/181827257201331194610634/ Eclipse 安装最新SVN插件 2013 ...

  9. 用For Each语句对Session.Contents树组进行遍历

    <%@ LANGUAGE=VBScript codepage ="936" %> <% Option Explicit %> 您的sessionID号是:& ...

  10. iOS View 模糊效果(毛玻璃)

    iOS View 模糊效果(毛玻璃)   相关资料 http://stackoverflow.com/questions/18404907/using-gpuimage-to-recreate-ios ...