Sicily 1148. 过河

1148. 过河

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。

题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。

Input

输入的第一行有一个正整数L(1 <= L <= 109),表示独木桥的长度。第二行有三个正整数S,T,M,分别表示青蛙一次跳跃的最小距离,最大距离,及桥上石子的个数,其中1 <= S <= T <= 10,1 <= M <= 100。第三行有M个不同的正整数分别表示这M个石子在数轴上的位置(数据保证桥的起点和终点处没有石子)。所有相邻的整数之间用一个空格隔开。

Output

输出只包括一个整数,表示青蛙过河最少需要踩到的石子数。

Sample Input

102 3 52 3 5 6 7

Sample Output

2

// Problem#: 1148
// Submission#: 3237242
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <algorithm>
#include <iostream>
#include <string>
#include <stdio.h>
#include <queue>
#include <string.h>
#include <vector>
#include <iomanip>
#include <map>
#include <stack>
#include <functional>
#include <list>
#include <cmath>
using namespace std;

const int MAX = 10050;

int main() {

    std::ios::sync_with_stdio(false);

    while (1) {
    
        int L;
        int dp[MAX];
        int stone[MAX];
        int stonePos[105];
        int s, t, m;
        cin >> L >> s >> t >> m;
        if (cin.eof()) break;
        stonePos[0] = 0;
        for (int i = 1; i <= m; i++) cin >> stonePos[i];
        sort(stonePos + 1, stonePos + m + 1);

        if (s == t) {  // 由于后面有状态压缩,所以这里要进行特殊情况的处理
            int ans = 0;
            for (int i = 1; i <= m; i++) {
                if (stonePos[i] % s == 0) ans++;
            }
            cout << ans << endl;
            continue;
        }

        for (int i = 1; i <= m; i++) {  // 状态压缩,如果两个石头的距离大于90,就设为90
            if (stonePos[i] - stonePos[i - 1] > 90) {
                int moveDistance = stonePos[i] - (stonePos[i - 1] + 90);
                for (int j = i; j <= m; j++) stonePos[j] -= moveDistance;
            }
        }

        for (int i = 0; i < MAX; i++) stone[i] = 0;
        for (int i = 1; i <= m; i++) stone[stonePos[i]] = 1;
        for (int i = 1; i < MAX; i++) dp[i] = -1;
        dp[0] = 0;
        L = stonePos[m] + 90;
        for (int i = 0; i < L; i++) {
            if (dp[i] == -1) continue;
            for (int j = i + s; j <= i + t; j++) {
                if (dp[j] == -1 || dp[i] + stone[j] < dp[j]) dp[j] = dp[i] + stone[j];
            }
        }
        int ans = MAX;
        for (int i = L; i < L + t; i++) if (ans > dp[i] && dp[i] != -1) ans = dp[i];
        cout << ans << endl;

    }

    //getchar();
    //getchar();
    
    return 0;
}                                 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值