码迷,mamicode.com
首页 > 其他好文 > 详细

P1052 过河

时间:2018-10-01 21:37:42      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:algo   include   难度   play   display   sort   简单   最优   注意   

事后觉得又简单又难。。。

事后觉得又简单又难。。。

这道题如果这个\(l\)不大的话就是一道水得不得了的水题,不过数据那么大就有点难度了。

显然我们可以离散化,具体的操作就是缩点与点之间的距离。我这里用到的是2520缩。

\[2520=lcm(1,2,3,...,10)且1 \leq s \leq t \leq 10\]

所以我们对相邻两点之间的距离直接%2520。

但注意对\(s=t\)情况的处理。我参考了题解里面的一种做法。

缩完点之后的最后一块石头显然不是终点,真正的终点我们要弄出来。

我们在最后一块石头为首的\(t\)长度区间寻找出答案的最小值,我我们转移状态可能从其中任意元素作为终点,并且我们取答案最小的,就是最优的。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn = 500005;

int l, s, t, m;

int dp[maxn];
int stone[105], newstone[105], newl;
bool havestone[maxn];

void solve()
{
    int now = 0, ans = 0;
    for(int i = 1; i <= m; i++)
    {
        if((stone[i] - now) % s == 0)
        {
            now = stone[i];
            ans++;
        }
        else if(now + (stone[i] - now) % s <= l) now = now + (stone[i] - now) % s;
    }
    printf("%d\n", ans);
}
int main()
{
    scanf("%d%d%d%d", &l, &s, &t, &m);
    for(int i = 1; i <= m; i++) scanf("%d", &stone[i]);
    std::sort(stone + 1, stone + m + 1);
    memset(dp, 0x3f, sizeof dp);
    for(int i = 1; i <= m; i++)
    {
        newstone[i] = newstone[i - 1] + ((stone[i] - stone[i - 1]) % 2520);
        havestone[newstone[i]] = true;
    }
    dp[0] = 0;
    for(int i = 1; i <= newstone[m] + t; i++)
    {
        for(int j = t; j >= s; j--)
        {
            if(i - j >= 0)
            {
                dp[i] = std::min(dp[i], dp[i - j] + (int)(havestone[i]));
            }
        }
    }
    int ans = 0x3f3f3f3f;
    for(int i = newstone[m]; i <= newstone[m] + t; i++) ans = std::min(ans, dp[i]);
    printf("%d\n", ans);
    return 0;
}

P1052 过河

标签:algo   include   难度   play   display   sort   简单   最优   注意   

原文地址:https://www.cnblogs.com/Garen-Wang/p/9735707.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!