• 【NOIP2014】飞扬的小鸟


    本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P1941


    怎么会有这么迷的一道题!

    明明思路很简单,但要想A掉,细节怎么就不好想呢!

    很显然的DP,状态一目了然,处理好特殊情况,一步步推就可以了。

    DP有刷表法和填表法,为了推的过程中特判是否到最高处省事,我选择了刷表法,80分,TLE了四个点,需要优化。超时主要是在于转移上,一个状态近似可以转移到m个状态,优化是当发现某次无法取得更优解,就剪枝,因为再往下肯定不会更优。而且需要从m到1枚举,可能这样会剪去更多的枝,好玄。。。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 inline int get_num() {
     8     int num = 0;
     9     char c = getchar();
    10     while (c < '0' || c > '9') c = getchar();
    11     while (c >= '0' && c <= '9')
    12         num = num * 10 + c - '0', c = getchar();
    13     return num;
    14 }
    15 
    16 const int maxn = 1e4 + 5, maxm = 1e3 + 5, inf = 0x3f3f3f3f;
    17 
    18 int tube[2][maxn], updown[2][maxn], dp[maxn][maxm];
    19 //0为下,1为上
    20 
    21 int main() {
    22     int n, m, k, ans = inf, cnta = 0, cntb = 0;
    23     n = get_num(), m = get_num(), k = get_num();
    24     for (int i = 0; i < n; ++i)
    25         updown[1][i] = get_num(), updown[0][i] = get_num();
    26     memset(tube[1], inf, sizeof(tube[1]));
    27     for (int i = 1; i <= k; ++i) {
    28         int p = get_num(), l = get_num(), h = get_num();
    29         tube[0][p] = l, tube[1][p] = h;
    30     }
    31     memset(dp, inf, sizeof(dp));
    32     memset(dp[0], 0, sizeof(dp[0]));
    33     for (int i = 0; i <= n; ++i)
    34         for (int j = m; j >= 0; --j) {
    35             if (dp[i][j] == inf) continue;
    36             if (i == n) {ans = min(ans, dp[i][j]); continue;}
    37             cnta = max(cnta, i);
    38             int next = j - updown[0][i], cnt;
    39             if (next > tube[0][i + 1] && next < tube[1][i + 1])
    40                 dp[i + 1][next] = min(dp[i + 1][next], dp[i][j]);
    41             next = j + updown[1][i], cnt = 1;
    42             if (next > m) next = m;
    43             while (next <= m) {
    44                 if (dp[i][j] + cnt > dp[i + 1][next]) break;
    45                 if (next > tube[0][i + 1] && next < tube[1][i + 1])
    46                     dp[i + 1][next] = min(dp[i + 1][next], dp[i][j] + cnt);
    47                 if (next == m) break;
    48                 next += updown[1][i], ++cnt;
    49                 if (next > m) next = m;
    50             }
    51         }
    52     if (ans < inf) printf("1
    %d", ans);
    53     else {
    54         for (int i = 0; i <= cnta; ++i)
    55             if (tube[1][i] < inf) ++cntb;
    56         printf("0
    %d", cntb);
    57     }
    58     return 0;
    59 }
    AC代码
  • 相关阅读:
    -1.#IND000 &&图像类型转换
    三维点集拟合:平面拟合、RANSAC、ICP算法
    深度学习:又一次推动AI梦想(Marr理论、语义鸿沟、视觉神经网络、神经形态学)
    三维重建:Kinect几何映射-SDK景深数据处理
    《SLIC Superpixels》阅读笔记
    中国企业系列
    关于抠图的一些文章方法收集
    数学空间引论
    PCL:解决PCL和OpenCV冲突的方法
    游戏开发:OpenGL入门学习
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9835363.html
Copyright © 2020-2023  润新知