(第二场)A Run 【动态规划】

记忆化搜索解决运动路径问题
本文介绍了一道关于运动路径选择的算法题,通过记忆化搜索和动态规划的方法解决了小白在不同距离内的运动路径数量问题。文章详细解析了解题思路,并给出了完整的AC代码。

链接:https://www.nowcoder.com/acm/contest/140/A

题目描述:

White Cloud is exercising in the playground.
White Cloud can walk 1 meters or run k meters per second.
Since White Cloud is tired,it can't run for two or more continuous seconds.
White Cloud will move L to R meters. It wants to know how many different ways there are to achieve its goal.
Two ways are different if and only if they move different meters or spend different seconds or in one second, one of them walks and the other runs.

输入描述:

The first line of input contains 2 integers Q and k.Q is the number of queries.(Q<=100000,2<=k<=100000)
For the next Q lines,each line contains two integers L and R.(1<=L<=R<=100000)

输出描述:

For each query,print a line which contains an integer,denoting the answer of the query modulo 1000000007.

案例

输入:

3 3
3 3
1 4
1 5

输出:

2
7
11

大概题意:

小白喜欢运动,他每秒可以走一米或者跑K米,有Q次查询,每次查询求跑0 ~ 【L,R】米的方案数;

 

思路:

一开始看到这道题想着是道规律题,结果花时间列数据找规律。。。

果然还是too young too simple,师兄花了短短的时间AC之后在群里丢给我们八个字“记忆化搜索,过了”。

想了那么多,这就是道纯粹的DP了啊,关键在于分开跑和走的方案,不能连续跑

 

状态:

dp[i][0] 走 i  meters 的方案数

dp[i][1] 跑 i meters 的方案数

转移方程:

dp[i][0] = dp[i-1][1] + dp[i-1][0];

dp[i][1] = dp[i-k][0] (注意题目条件:不能连续跑,有队友一直卡在60%这里的原因)

!!!更新dp值的同时也要更新前缀和sum[i] (用于最后求答, 本人傻傻的还在后面查询的时候才计算前缀和,一直T)!!!

AC code:

#include <cstdio>
#include <iostream>
#include <cstring>
#define mod 1000000007
using namespace std;

const int maxk = 100005;

int Q, k;
long long int dp[maxk][2], sum[maxk];

int main()
{
    scanf("%d%d", &Q, &k);
    for(int i = 0; i < k; i++)
    {
        dp[i][0] = 1;
        dp[i][1] = 0;
        if(i > 0)
        sum[i] = sum[i-1] + dp[i][0]+dp[i][1];
    }
    dp[k][1] = 1;
    sum[k] = sum[k-1] + dp[k][1];
    for(int i = k; i < maxk; i++)
    {
        dp[i][0] = ((dp[i-1][0] + dp[i-1][1]))%mod ;
        dp[i][1] = dp[i-k][0];
        sum[i] = sum[i-1]+dp[i][0]+dp[i][1];
    }
    while(Q--)
    {
        int L, R;
        long long int ans = 0;
        scanf("%d%d", &L, &R);
        ans =(sum[R] - sum[L-1] + mod)%mod;
        printf("%lld\n", ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/ymzjj/p/9348759.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值