codeforces div2 677 D
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的更多相关文章
- Codeforces Round #677 (Div. 3) 题解
Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...
- codeforces DIV2 D 最短路
http://codeforces.com/contest/716/problem/D 题目大意:给你一些边,有权值,权值为0的表示目前该边不存在,但是可以把0修改成另外一个权值.现在,我们重新建路, ...
- codeforces div2.C
C. New Year and Rating time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- codeforces div2 603 D. Secret Passwords(并查集)
题目链接:https://codeforces.com/contest/1263/problem/D 题意:有n个小写字符串代表n个密码,加入存在两个密码有共同的字母,那么说这两个密码可以认为是同一个 ...
- codeforces div2 603 E. Editor(线段树)
题目链接:https://codeforces.com/contest/1263/problem/E 题意:一个编译器,每次输入一些字符,R表示光标右移,L表示光标左移,然后有一些左括号( 和 右括 ...
- 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到 ...
- Codeforces Round #677 (Div. 3) D/1433D Districts Connection
https://codeforces.com/contest/1433/problem/D 找两个不同权值的节点A.B连起来,所有与A不同权值的连到A上,相同的连到B上. #include<io ...
- Codeforces Round #677 (Div. 3) G. Reducing Delivery Cost(dijkstra算法)
题目链接:https://codeforces.com/contest/1433/problem/G 题解 跑 \(n\) 遍 \(dijkstra\) 得到任意两点间的距离,然后枚举哪一条边权为 \ ...
- Codeforces Round #677 (Div. 3)【ABCDE】
比赛链接:https://codeforces.com/contest/1433 A. Boring Apartments 题解 模拟即可. 代码 #include <bits/stdc++.h ...
随机推荐
- 搭建localhost的目录环境
.打开系统盘,默认是C:\Windows\System32\drivers\etc,如果系统盘是D盘就打开D:\Windows\System32\drivers\etc: .用记事本打开hosts: ...
- mongoDB7--游标
之前我们学习了"增删改查"四中语法和查询表达式的深入学习,我们已经掌握了一定的操作mongodb数据的能力,那么接下来我们就要考虑我们的操作的效率问题了.(1)游标介绍如果我们查询 ...
- 项目管理实践【四】Bug跟踪管理【Bug Trace and Management】
首先,向大家说一声抱歉,这篇文章耽误了这么久才和大家见面.至于Bug的跟踪和管理的必要性和好处,我就不在这里说了,下面介绍几款Bug跟踪和管理的软件. 一.BugNET BugNET是一个非常优秀的开 ...
- MyBatis学习-SQL 符号篇
当我们需要通过 XML 格式处理 SQL 语句时,经常会用到 <,<=,>,>= 等符号,但是很容易引起 XML 格式的错误,这样会导致后台将 XML 字符串转换为 XML文档 ...
- Windows常用的监视数据指标
- JavaScript高级程序设计:第一章
JavaScript简介: 1.JavaScript实现应该由以下三部分组成: (1)核心:ECMAScript (2)文档对象模型:DOM (3)浏览器对象模型:BOM 2.什么是ECMAScrip ...
- linux中的 tar命令的 -C 参数,以及其它一些参数(转)
linux中的 tar命令的 -C 参数,以及其它一些参数 复制源:http://www.cnblogs.com/li-hao/archive/2011/10/03/2198480.htmltar命令 ...
- Entity Framework技巧系列之八 - Tip 29 – 34
提示29. 怎样避免延迟加载或Load()阅读器问题 如果你有如下这样的代码: 1 var results = from c in ctx.Customers 2 where c.SalesPerso ...
- ASP.NET MVC Controller向View传值的几种方式
上几篇博文提到MVC和WebForm的区别,主要是MVC的Controller和View将传统的WebForm的窗体和后台代码做了解耦,这篇博文简单介绍一下在MVC中Controller向View是如 ...
- insertRule()与addRule()创建规则
要向现有的样式表中添加新规则,需要使用insertRule()方法.这个方法接受两个参数:规则文本和表示在那里插入规则的索引.下面是一个例子: sheet.insertRule("body ...