zoukankan      html  css  js  c++  java
  • 洛谷P1052 过河【线性dp】【离散化】

    题目https://www.luogu.org/problemnew/show/P1052

    题意:

    青蛙要从0跳到超过$l$的地方,每一次可以跳$s$到$t$之间的任意数。

    在河中有m个石头,要求在尽量不要跳到石头的情况下,青蛙最少可能会跳到多少颗石头。

    思路:

    刚开始很自然的想到就是用dp[i]表示跳到坐标i时最少要跳到多少时候,dp[i]可以用dp[i-(s~t)]转移过来。

    但是一看数据范围,坐标最大是1e9,t是10,时间空间都不够。

    再一看m范围才100,这种情况下就要想到用离散化。

    因为跳的距离大于t和小于t其实是一样的。对于大于t的某数k,一定可以通过跳x次t步再跳k%t步到达k。

    对于石头之间距离超过t的,都可以把中间的距离压缩至t~2t之间。

    之所以不是0~t是因为,0~s之间的距离是跳不到的但是t~t+s是可以跳到的。他们并不等价。

    然后再用上面说的dp就可以了。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<map>
     4 #include<set>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<cmath> 
     9 #include<stack>
    10 #include<queue>
    11 #include<iostream>
    12 
    13 #define inf 0x7fffffff
    14 using namespace std;
    15 typedef long long LL;
    16 typedef pair<string, string> pr;
    17 
    18 int l, s, t, m;
    19 const int maxn = 105;
    20 int stone[maxn]; 
    21 int dp[maxn * 20];
    22 int vis[maxn * 20];
    23 
    24 int main()
    25 {
    26     scanf("%d%d%d%d", &l, &s, &t, &m);
    27     for(int i = 1; i <= m; i++){
    28         scanf("%d", &stone[i]);
    29     }
    30     stone[0] = 0;stone[m + 1] = l;
    31     sort(stone, stone + 2 + m);
    32     int far = 0;
    33     for(int i = 1; i <= m + 1; i++){
    34         if(stone[i] - stone[i - 1] > t){
    35             far += (stone[i] - stone[i - 1]) % t + t;
    36         }
    37         else{
    38             far += (stone[i] - stone[i - 1]);
    39         }
    40         vis[far] = 1;
    41     }
    42     vis[far] = 0;vis[0] = 0;
    43     //cout<<far<<endl;
    44     
    45     memset(dp, 0x3f, sizeof(dp));
    46     dp[0] = 0;
    47     
    48     for(int i = 1; i <= far + t - 1; i++){
    49         for(int j = s; j <= t; j++){
    50             if(i - j >= 0){
    51                 dp[i] = min(dp[i], dp[i - j] + vis[i]);
    52             }
    53         }
    54     }
    55     
    56     int ans = 500;
    57     for(int i = far; i <= far + t - 1; i++){
    58         ans = min(ans, dp[i]);
    59     }
    60     printf("%d
    ", ans);
    61     
    62     return 0; 
    63 }
  • 相关阅读:
    修改IIS下默认的ASP.NET版本。
    smo算法
    支持向量机通俗导论
    二次规划
    交叉熵
    机器学习中的维数灾难
    矩阵与线性变换
    l2正则化
    Matlab 的reshape函数
    matlab 等值线函数 contour
  • 原文地址:https://www.cnblogs.com/wyboooo/p/10858812.html
Copyright © 2011-2022 走看看