• Codeforces Round #355 (Div. 2) D. Vanya and Treasure


    题目大意: 给你一个n × m 的图,有p种宝箱, 每个点上有一个种类为a[ i ][ j ]的宝箱,a[ i ][ j ] 的宝箱里有 a[ i ][ j ] + 1的钥匙,第一种宝箱是没有锁的,

    第p类宝箱只有一个且里面由宝藏,你现在在(1 ,1)问你最少需要多少步才能拿到宝藏。 (n, m <= 300)

    思路:这题真的好恶心啊。。。  我们考虑p类宝箱只能从p - 1类转移过来, 这样我们就能从第一类宝箱开始往后递推, 但是最坏的情况, p 类 和p - 1类,都有45000

    个点, 那么复杂度就会很大。。。  所以我们要分类讨论, 对于 (p.size()) * (p + 1. size()) > n * m 的点我们在图上进行暴力转移,复杂度微n × m, 否则我们直接暴力

    转移。。。

      1 #include<bits/stdc++.h>
      2 #define LL long long
      3 #define fi first
      4 #define se second
      5 #define mk make_pair
      6 #define pii pair<int,int>
      7 #define piii pair<int, pair<int,int>>
      8 using namespace std;
      9 
     10 const int N=300+1;
     11 const int M=1e4+7;
     12 const int inf=0x3f3f3f3f;
     13 const LL INF=0x3f3f3f3f3f3f3f3f;
     14 const int mod=1e9 + 7;
     15 
     16 vector<pair<int, pii>> vec[N * N];
     17 int n, m, p, idx, a[N][N], S, T, f[N * N], hs[N][N], vis[N][N];
     18 bool flag[N][N];
     19 int dx[] = {1, -1, 0, 0}, dy[] = {0 ,0 , 1, -1};
     20 
     21 int dis(pii &a, pii &b) {
     22     return abs(a.fi - b.fi) + abs(a.se - b.se);
     23 }
     24 
     25 bool check(int x, int y) {
     26     if(x < 1 || x > n) return false;
     27     if(y < 1 || y > m) return false;
     28     return true;
     29 }
     30 
     31 void bfs(int p) {
     32     for(int i = 1; i <= n; i++) {
     33         for(int j = 1; j <= m; j++) {
     34             flag[i][j] = false;
     35             vis[i][j] = inf;
     36         }
     37     }
     38     queue<piii> Q;
     39     for(auto u : vec[p]) {
     40         Q.push(mk(f[u.fi], u.se));
     41         vis[u.se.fi][u.se.se] = f[u.fi];
     42     }
     43 
     44     while(!Q.empty()) {
     45         piii u = Q.front(); Q.pop();
     46         for(int i = 0; i < 4; i++) {
     47             piii nx = mk(vis[u.se.fi][u.se.se] + 1, mk(u.se.fi + dx[i], u.se.se + dy[i]));
     48             if(check(nx.se.fi, nx.se.se)) {
     49                 if(vis[nx.se.fi][nx.se.se] > nx.fi)
     50                 {
     51                     vis[nx.se.fi][nx.se.se] = nx.fi;
     52                     if(!flag[nx.se.fi][nx.se.se]) {
     53                         flag[nx.se.fi][nx.se.se] = true;
     54                         Q.push(nx);
     55                     }
     56                 }
     57             }
     58         }
     59         flag[u.se.fi][u.se.se] = false;
     60     }
     61 
     62     for(auto u : vec[p + 1]) {
     63         f[u.fi] = vis[u.se.fi][u.se.se];
     64     }
     65 }
     66 
     67 int main() {
     68     memset(f, inf, sizeof(f));
     69 
     70     scanf("%d%d%d", &n, &m, &p);
     71     for(int i = 1; i <= n; i++)
     72         for(int j = 1; j <= m; j++)
     73             scanf("%d", &a[i][j]);
     74 
     75     for(int i = 1; i <= n; i++) {
     76         for(int j = 1; j <= m; j++) {
     77             vec[a[i][j]].push_back(mk(++idx, mk(i, j)));
     78             hs[i][j] = idx;
     79             if(a[i][j] == p) {
     80                 S = 0;
     81                 T = idx;
     82             }
     83         }
     84     }
     85     f[0] = 0;
     86     vec[0].push_back(mk(0, mk(1, 1)));
     87     for(int i = 1; i <= p; i++) {
     88         if(vec[i - 1].size() * vec[i].size() <= n * m) {
     89             for(auto u : vec[i - 1]) {
     90                 for(auto v : vec[i]) {
     91                     f[v.fi] = min(f[v.fi], f[u.fi] + dis(u.se, v.se));
     92                 }
     93             }
     94         } else {
     95             bfs(i - 1);
     96         }
     97     }
     98     printf("%d
    ", f[T]);
     99     return 0;
    100 }
    101 /*
    102 */
  • 相关阅读:
    CSS定位
    使用开源框架进行get,post提交
    使用httpclient框架分别用post,get方式提交
    C++ const_cast
    C++ 类继承 常量对象调用函数
    C++ 类继承 子类调用父类
    C++ explicit关键字
    C++ class入门
    C#检测耗时操作
    面向对象编程入门
  • 原文地址:https://www.cnblogs.com/CJLHY/p/8992448.html
Copyright © 2020-2023  润新知