链接

Codeforces 677D Vanya and Treasure

题意

n*m中有p个type,经过了任意一个 type=i 的各自才能打开 type=i+1 的钥匙,最初有type=1的钥匙, 问拿到type=p的钥匙最少需要走多少步

思路

第一想法就是按type来递推, 将type相同的存到一起,dp[i][j]=min(dp[i][j], dp[k][l]+distance([i][j], [k][l])),其中 a[i][j] = a[k][l]+1. 但这样type相同的个数较多时就超时了,所以根据type的个数,较多时使用BFS就可以了。 我没有仔细研究时间复杂度就过了,官方题解好像有均摊复杂度的证明。

代码

#include <iostream>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <string> #define LL long long
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MOD 1000000007
using namespace std; struct POS{
int x, y;
POS(int x = 0, int y = 0) :x(x), y(y){};
};
vector<POS> s[90005];
int a[305][305];
int d[305][305];
bool vis[305][305];
int dp[305][305];
const int step[4][2] = { 1, 0, 0, 1, -1, 0, 0, -1 };
int get_distance(POS &a, POS &b){
return abs(a.x - b.x) + abs(a.y - b.y);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
int n, m, p;
while (~scanf("%d%d%d", &n, &m, &p)){
int x;
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j){
scanf("%d", &a[i][j]);
s[a[i][j]].push_back(POS(i, j));
}
}
memset(dp, INF, sizeof(dp));
for (int i = 0; i < s[1].size(); ++i){
dp[s[1][i].x][s[1][i].y] = s[1][i].x + s[1][i].y - 2;
}
for (int i = 2; i <= p; ++i){
if (s[i].size() * s[i - 1].size() < n * m){
for (int j = 0; j < s[i].size(); ++j){
POS J = s[i][j];
for (int k = 0; k < s[i - 1].size(); ++k){
POS K = s[i - 1][k];
dp[J.x][J.y] = min(dp[K.x][K.y] + get_distance(J, K), dp[J.x][J.y]);
}
}
}
else{
memset(d, INF, sizeof(d));
memset(vis, 0, sizeof(vis));
queue<POS> Q;
for (int j = 0; j < s[i - 1].size(); ++j){
POS J = s[i - 1][j];
Q.push(J);
vis[J.x][J.y] = true;
d[J.x][J.y] = dp[J.x][J.y];
}
while (!Q.empty()){
POS u = Q.front();
Q.pop();
vis[u.x][u.y] = false;
for (int j = 0; j < 4; ++j){
int x = u.x + step[j][0];
int y = u.y + step[j][1];
if (a[u.x][u.y] == i) dp[u.x][u.y] = min(dp[u.x][u.y], d[u.x][u.y]);
if (x < 1 || x > n || y < 1 || y > m) continue;
if (d[x][y] > d[u.x][u.y] + 1){
d[x][y] = d[u.x][u.y] + 1;
if (!vis[x][y]){
vis[x][y] = true;
if (a[x][y] == i){
dp[x][y] = min(dp[x][y], d[x][y]);
}
Q.push(POS(x, y));
}
}
}
}
}
}
POS K = s[p][0];
cout << dp[K.x][K.y] << endl;
}
}

Codeforces 677D Vanya and Treasure 暴力+BFS的更多相关文章

  1. CodeForces 677D. Vanya and Treasure 枚举行列

    677D. Vanya and Treasure 题意: 给定一张n*m的图,图上每个点标有1~p的值,你初始在(1,1)点,你必须按照V:1,2,3...p的顺序走图上的点,问你如何走时间最少. 思 ...

  2. Codeforces 677D - Vanya and Treasure - [DP+优先队列BFS]

    题目链接:http://codeforces.com/problemset/problem/677/D 题意: 有 $n \times m$ 的网格,每个网格上有一个棋子,棋子种类为 $t[i][j] ...

  3. CodeForces 677D Vanya and Treasure

    $dp$,树状数组. 很明显这是一个$DAG$上的$dp$,由于边太多,暴力$dp$会超时,需要优化. 例如计算$dp[x][y]$,可以将区域分成四块,$dp[x][y]$取四块中的最小值,每一块用 ...

  4. 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 ...

  5. codeforces 677D D. Vanya and Treasure(二维线段树)

    题目链接: D. Vanya and Treasure time limit per test 1.5 seconds memory limit per test 256 megabytes inpu ...

  6. 题解-CF677D Vanya and Treasure

    CF677D Vanya and Treasure 有一个 \(n\times m\) 的矩阵 \(a(1\le a_{i,j}\le p)\),求从起点 \((1,1)\) 出发依次遍历值为 \(1 ...

  7. hdu 1195:Open the Lock(暴力BFS广搜)

    Open the Lock Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  8. codeforces 492E. Vanya and Field(exgcd求逆元)

    题目链接:codeforces 492e vanya and field 留个扩展gcd求逆元的板子. 设i,j为每颗苹果树的位置,因为gcd(n,dx) = 1,gcd(n,dy) = 1,所以当走 ...

  9. codeforces 677D(分层图dp)

    Codeforces 677D 传送门:https://codeforces.com/contest/677/problem/D 题意: 给你一个n*m的方格图,每个点有一个权值val,现在要求你从坐 ...

随机推荐

  1. Python笔记(四)

    # -*- coding:utf-8 -*- # 控制语句 # if...else... print "********************1********************** ...

  2. SQlException 对象名无效

  3. struts2学习之基础笔记1

    第6章 Strusts 2框架 1  引出 Web App  àà MVC  àà View 视图(jsp,html,JS) | C(Servlet)Filter,Listneer | M(数据bea ...

  4. jmeter的认识——线程组的认识

    名称:可以给线程组设置一个个性化的命名 注释:可以对线程组添加备注以标记 在取样器错误后要执行的动作:就是在错误之后要如何执行,可选继续执行后续的.停止执行等. 线程数:就是需要设置多少线程执行测试. ...

  5. 彻底解决降级安装失败无法彻底卸载应用bug

    彻底解决魅族手机无法彻底卸载应用bug使用Flyme系统的同学可能会遇到一个问题:卸载了某些软件(例如通过开发者模式调试安装的应用)后,实际这个应用还残留在系统,当你用低版本或者其他签名的apk覆盖安 ...

  6. Broadcast Receiver广播接收器

    1.概述 广播接收器不仅能接受来自系统的内容,也可以接受来自其他app的内容.广播分为标准广播和有序广播. 2.标准广播 一种完全异步执行的广播,在广播发出之后几乎所有的广播接收器都在同一时刻接受到广 ...

  7. 使用CocoaPods更新第三方库出错的解决办法

    使用CocoaPods更新第三方库出错的解决办法 执行完pod install或pod update之后,控制台抛出以下警告信息: [!] The xx [Debug] target override ...

  8. const使用总结

    1.常变量:  const 类型说明符 变量名    const int a; 常引用:  const 类型说明符 &引用名   const int &a; 常对象:  类名 cons ...

  9. ZBrush中标准几何体与Polymesh

    通过对ZBrush的学习,相信您已经对这款软件有了一定的了解,文本我们主要学习ZBrush®的3D物体标准几何体的特性和使用方法.在ZBrush中只有Polymesh(多边形网格)物体才能使用雕刻笔刷 ...

  10. JS实现HTML打印机效果

    5月最近在学Django,所以所有的Demo都没有PO出去 <!DOCTYPE html> <html lang="en"> <head> &l ...