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 ...
随机推荐
- sql注入绕过union select过滤
# # # #WAF Bypassing Strings: /*!%55NiOn*/ /*!%53eLEct*/ ,,)-- - +union+distinct+select+ +union+dist ...
- Default Constructor的构造操作
Default Constructor的构造操作 C++ Annotated Reference Manual书中的Section 12.1说过:default constructor 只有在编译器需 ...
- TCP/IP,http,socket,长连接,短连接
TCP/IP TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层. 在网络层有IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议. 在传输层中有TCP协议与UDP协议. 在应 ...
- OpenCV:二值图像连通区域分析与标记算法实现
http://blog.csdn.net/cooelf/article/details/26581539?utm_source=tuicool&utm_medium=referral Open ...
- C#在Json反序列化中处理键的特殊字符
假设有如下Json 数据: 1.{ 2."id" : 1, 3."@value" : "this a @", 4."$p" ...
- BZOJ3036绿豆蛙的归宿
BZOJ3036绿豆蛙的归宿 锲下陟凝 褰宓万 郝瓦痕膳 叶诙摞 А知π剧 椐猊∫距 屠缲佗 ゲ蕖揪 俜欧彖鹤 磲砩ほ #琛扶 觅电闸ス 捆鳢げ 浜窠 魂睨"烁 蕞滗浼 洒ヂ跪 ...
- win10快捷键大全
win10快捷键大全大家可以来了解一下,今天小编带来了win10常用快捷键,很多朋友喜欢使用快捷键来操作电脑,那么Windows10系统有哪些新的快捷键呢• 贴靠窗口:Win +左/右> Win ...
- 暴力+树状数组维护 Codeforces Round #378 (Div. 2) C
题目大意:给你一个长度为n的数组a,然后数值大的可以合并数值小的,且合并了以后该数组的长度-1.给你一个长度为k目标数组b,问,是否可以从a数组变到b数组,是就yes并且输出步骤.否就输出no 思路: ...
- Qt学习之系列[9] – QCoreApplication:processEvents()可能会引起递归,导致栈溢出崩溃
api含义:QCoreApplication::processEvents() 将处理所有事件队列中的事件并返回给调用者. 问题描述: 当主线程在某个槽函数里正在执行processEvents时, 刚 ...
- Inno Setup入门(十)——操作注册表
有些程序需要随系统启动,或者需要建立某些文件关联等问题,这些都是通过在安装程序中对注册表进行操作的结果.Inno Setup中通过[registry]段实现对注册表的操作. 本段说明: 参数列表: 参 ...