• 【NOIP2005】过河


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


    显然可以拿到30分暴力分,直接开一个10^9的数组,然后跑最裸的DP就可以了。

    但怎么优化呢?这里有一种不错的方法——路径压缩。和并查集里那个并不完全一样。

    注意,我们只关注路径上有没有石头,而不关注路径是怎么走的,因此可以把两块石头之间的距离压缩。这里我们参考小凯的疑惑里推出的结论,假如每次走a或a+1步,那么大于等于a*(a+1)的步数均可以走出,这样我们把大于t*(t-1)步的距离压缩成t*(t-1)步即可,而t<=10,所以压缩完后,肯定不会炸空间。压缩完后再跑裸DP。

    但注意这里我们用到了可以走t-1或t步,如果s=t就不满足,需要讨论,其实也很简单,就是数数有多少块石头的位置是s或t的倍数即可。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 const int maxn = 1e4 + 15, inf = 0x3f3f3f3f;
     8 
     9 int dp[maxn], stone[105], cnt[maxn];
    10 
    11 int main() {
    12     int l, s, t, m, last = 0, ans = inf, ans2 = 0;
    13     scanf("%d%d%d%d", &l, &s, &t, &m);
    14     l = 0;
    15     for (int i = 1; i <= m; ++i) scanf("%d", &stone[i]);
    16     sort(stone + 1, stone + m + 1);
    17     for (int i = 1; i <= m; ++i) {
    18         int d = stone[i] - stone[i - 1];
    19         if (d > t * (t - 1)) d = t * (t - 1);
    20         cnt[last += d] = 1;
    21         l = max(l, last);
    22         if (stone[i] % s == 0) ++ans2;
    23     }
    24     if (s == t) {printf("%d", ans2);return 0;}
    25     memset(dp, inf, sizeof(dp));
    26     dp[0] = 0;
    27     for (int i = 0; i < l; ++i)
    28         for (int j = s; j <= t; ++j) {
    29             dp[i + j] = min(dp[i + j], dp[i] + cnt[i + j]);
    30             if (i + j >= l) ans = min(ans, dp[i + j]);
    31         }
    32     printf("%d", ans);
    33     return 0;
    34 }
    AC代码
  • 相关阅读:
    Leetcode | Work Break I & II
    X-Japan
    Leetcode | Gas Station
    jstring, String, char* 变换函数
    动态链接库的创建
    C语言实现md5函数代码
    ARM汇编指令集
    2014年 各类黑客工具包
    ARM汇编指令的一些总结-转
    ARM指令集学习总结-转载
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9806746.html
Copyright © 2020-2023  润新知