秋日独木桥之谜:玉液书院的智慧挑战

输入描述

第一行一个整数,表示独木桥的长度

第二行三个整数S T M,含义如上

第三行 M 个不同的正整数,表示这M个石子在数轴上的位置。

L -> [1,1000000]

S T -> [1,10]

M -> [1,100]

输出描述

一个整数,表示最少可以踩多少个石子

dfs深搜+剪枝:

  前期思考:

        1)由于本题的石头数量m比较少,因此会出现较多的空路,这里进行剪枝操作,因为大于s*t的空区间和s*t的区间等价,都不会导致石子数增加。

        2)转移方程为:dp[i] = min(dp[i],dp[i-j]+visit[i])                s<j<t

         具体含义为:前i个长度位置最少是dp[i]或dp[i]前s~t步内的最小踩石头数加i位置是否有石头,即能到i位置的所有位置最小的数

        3)到最后L位置其实和最后一个石头起到L前的所有位置的最小踩石头数相同,遍历这些dp找到最小值即可

特别的,如果s == t 那就只有唯一的一个结果,遍历后得到踩石头数。

#include <iostream>   
#include <algorithm>   
#include <cstring>   
using namespace std;   
#define IOS ios::sync_with_stdio(false);   
//代码预处理区   
   
const int INF = 0x3f3f3f3f;   
const int MAX = 1e6 + 7;   
int stone[107], now[107];   
int visited[MAX], dp[MAX];   
//全局变量区   
   
int main() {   
    IOS;   
    int l; cin >> l;   
    int s, t, m; cin >> s >> t >> m;   
    for (int i = 1; i <= m; i++) cin >> stone[i];   
    sort(stone + 1, stone + 1 + m);   
    if (s == t) {   
        int cnt = 0;   
        for (int i = 1; i <= m; ++i)   
            if (stone[i] % s == 0)cnt++;   
        cout << cnt << endl;   
        return 0;   
    }   
    now[0] = 0;   
    memset(visited, 0, sizeof visited);   
    for (int i = 1; i <= m; i++) {   
        int dis = stone[i] - stone[i - 1];   
        if (dis >= s * t) dis = s * t;   
        now[i] = now[i - 1] + dis;   
        visited[now[i]] = 1;   
    }   
    l = now[m] + s * t;   
    memset(dp, INF, sizeof dp);   
    dp[0] = 0;   
    for (int i = 1; i <= l; i++)   
        for (int j = s; j <= t; j++)   
            if (i >= j) dp[i] = min(dp[i], dp[i - j] + visited[i]);   
    int ans = INF;   
    for (int i = now[m]; i <= l; i++)   
        ans = min(ans, dp[i]);   
    cout << ans << endl;   
    return 0;   
}   
//函数区  

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值