zoukankan      html  css  js  c++  java
  • SOJ 1135. 飞跃原野

    解题技巧:

      1. 求从左上角到右下角的最短时间,可用BFS,一步为一个单位时间。

        BFS中的状态:人所在的行、列和能飞行的距离。

        每步选择的转移有:(i)不飞行到达相邻位置 (ii)使用飞行到达更远的地方。

        判断下一状态是否有效(是否可放入下一次进行BFS队列中)的根据是:下一状态的能量比以往相应位置的“能飞行的距离”充裕,即可以使用更大的“能飞行的距离”来寻找目的地。因为unit在递增。

      2.状态压缩:一个状态包括行、列和能飞行的距离,由于三者均<=100;故能压缩成一个整数。

    代码如下:

     1 #include <cstdio>
     2 #include <queue>
     3 using namespace std;
     4 const int maxm = 100;
     5 const int maxn = 100;
     6 
     7 char altas[maxm][maxn + 1];
     8 int max_energy[maxm][maxn];
     9 
    10 const int dm = 100000;
    11 const int dn = 1000;
    12 const int dd = 1;
    13 
    14 // 0-右,1-左,2-上,3-下
    15 int dx[4] = {0, 0, -1, 1};
    16 int dy[4] = {1, -1, 0, 0};
    17 
    18 void init(int m, int n) {
    19     for (int i = 0; i < m; ++i)
    20         for (int j = 0; j < n; ++j)
    21             max_energy[i][j] = -1;
    22 }
    23 
    24 int main() {
    25     int m, n, d;
    26     while (scanf("%d%d%d", &m, &n, &d) != EOF) {
    27         init(m, n); // 初始化
    28         for (int i = 0; i < m; ++i) scanf("%s", altas[i]);  // 输入地图
    29 
    30         if (m == 1 && n == 1) { // 特殊情况判断
    31             printf("0
    ");
    32             continue;
    33         }
    34         // bfs
    35         int start = 0 * dm + 0 * dn + d * dd;
    36         max_energy[0][0] = d;   // 初始状态的d最充足
    37         queue<int> que; que.push(start);
    38         int unit = 0;
    39         bool find = false;
    40         while (!que.empty() && !find) {
    41             ++unit;
    42             int size = que.size();
    43             while (size-- && !find) {
    44                 int state = que.front(); que.pop(); // 获取状态
    45                 int r = state / dm; // 状态还原
    46                 int c = state % dm / dn;
    47                 int e = state % dn;
    48 
    49                 // 找下一步可走位置
    50                 // 先环顾最近的四个方向一圈
    51                 for (int i = 0; i < 4 && !find; ++i) {
    52                     int next_m = r + dx[i];
    53                     int next_n = c + dy[i];
    54                     if (0 <= next_m && next_m < m && 0 <= next_n && next_n < n && altas[next_m][next_n] == 'P') {
    55                         if (e > max_energy[next_m][next_n]) {   // 后来的如果能量更加充足,可以重新启动该点
    56                             max_energy[next_m][next_n] = e;
    57                             int next_state = next_m * dm + next_n * dn + e * dd;
    58                             que.push(next_state);
    59                             if (next_m == m - 1 && next_n == n - 1) find = true;
    60                         }
    61                     }
    62                 }
    63                 // 再考虑飞行的可能
    64                 // 0-右,1-左,2-上,3-下
    65                 for (int i = 0; i < 4 && !find; ++i) {
    66                     for (int j = 2; j <= e && !find; ++j) {
    67                         int next_m = r + dx[i] * j;
    68                         int next_n = c + dy[i] * j;
    69                         if (0 <= next_m && next_m < m && 0 <= next_n && next_n < n) {
    70                             if (altas[next_m][next_n] == 'P') {
    71                                 if (e - j > max_energy[next_m][next_n]) {
    72                                     max_energy[next_m][next_n] = e - j;
    73                                     int next_state = next_m * dm + next_n * dn + (e - j) * dd;
    74                                     que.push(next_state);
    75                                     if (next_m == m - 1 && next_n == n - 1) find = true;
    76                                 }
    77                             }
    78                         } else {
    79                             break;
    80                         }
    81                     }
    82                 }
    83 
    84             }
    85         }
    86 
    87         if (find) printf("%d
    ", unit);
    88         else printf("impossible
    ");
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    HDU 5744
    HDU 5815
    POJ 1269
    HDU 5742
    HDU 4609
    fzu 1150 Farmer Bill's Problem
    fzu 1002 HangOver
    fzu 1001 Duplicate Pair
    fzu 1150 Farmer Bill's Problem
    fzu 1182 Argus 优先队列
  • 原文地址:https://www.cnblogs.com/mchcylh/p/5116679.html
Copyright © 2011-2022 走看看