Codeforces 479E Riding in a Lift(dp)

题目链接:Codeforces 479E Riding in a Lift

题目大意:有一栋高N层的楼,有个无聊的人在A层,他喜欢玩电梯,每次会做电梯到另外一层。但是这栋楼里有个秘

密实验室在B层,所以每次他移动的时候就有了一个限制,x为当前所在层,y为目标层,|x - y| < |x - b|。问说移动K次

后,有多少不同的路径。

解题思路:dp[i][j]表示在第i步到达j层有多少种不同的路径,dis = abs(j-B) - 1,那么在[j-dis,j+dis]这个范围都能被转

移,除了j。那么转移方程就很好写了。

但是直接转移的话复杂度有点高,因为转移的范围是成段的,所以我们可以利用数组维护区间和的方式取优化。每次对

一个区间l,r加上某个值v的时候,等于在l处+v,r+1处-v,最后处理的时候每个位置的准确值即为数组的前缀和。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>

using namespace std;

const int maxn = 5005;
const int mod = 1e9 + 7;

int N, A, B, K, dp[maxn][maxn];

void add (int idx, int l, int r, int d) {
    dp[idx][l] = (dp[idx][l] + d) % mod;
    dp[idx][r] = (dp[idx][r] - d + mod) % mod;
}

int main () {
    scanf("%d%d%d%d", &N, &A, &B, &K);

    dp[0][A] = 1;
    for (int i = 0; i < K; i++) {
        for (int j = 1; j <= N; j++) {
            if (j == B) continue;
            int x = abs(j - B) - 1;
            add(i+1, max(j-x, 1), j, dp[i][j]);
            add(i+1, j+1, min(j+x+1, N + 1), dp[i][j]);
        }

        int mv = 0;
        for (int j = 1; j <= N; j++) {
            mv = (mv + dp[i+1][j]) % mod;
            dp[i+1][j] = mv;
        }
    }

    int ans = 0;
    for (int i = 1; i <= N; i++)
        ans = (ans + dp[K][i]) % mod;
    printf("%d\n", ans);
    return 0;
}
时间: 2024-11-07 07:42:20

Codeforces 479E Riding in a Lift(dp)的相关文章

Codeforces 479E Riding in a Lift:前缀和/差分优化dp

题目链接:http://codeforces.com/problemset/problem/479/E 题意: 有一栋n层的房子. 还有一个无聊的人在玩电梯,每次玩电梯都会从某一层坐到另外一层. 他初始在a层,然后要玩k次电梯. 这栋楼里还有一个神秘实验室,在b层. 这让他每次坐电梯受到了限制: 当前在x层,然后要坐到y层,则必须满足|x-y|<|x-b| 问你共有多少种坐电梯的方案. 题解: 表示状态: dp[i][j] = numbers 表示当前在第i层,已经坐了j次电梯,此时的方案数.

CodeForces 479E Riding in a Lift

题意:给你一个n层楼的电梯,起始楼层为a,有一个楼层b永远都不能访问.假设你现在所在的楼层为 x ,目标楼层为y,y必须满足条件|x-y| < |x -b| 解题思路:时间复杂度是k×nxn,但是我们知道每次更新先把它存起来,然后到下一层再直接更新就行了,这里就需要用到前缀和.还要注意 mod 数加负数. 解题代码: 1 // File Name: 479e.cpp 2 // Author: darkdream 3 // Created Time: 2015年03月08日 星期日 21时37分1

Codeforces 480C Riding in a Lift dp

题目链接:点击打开链接 题意: 给定 n a b k 构造一个长度为k的序列. 使得序列中 对于任意两个相邻的数 | w[i-1] - w[i] | < | w[i] - b | 且第一个数 |a - w[1] | < | w[1] - b | 问: 有多少种不同的序列. 思路:dp 对于粗暴的dp复杂度是 n^3 我们可以用前缀和来优化掉一维的dp.. 反正是简单粗暴的题.具体看代码吧.. #include <cstdio> #include <iostream> #

Codeforces Round #274 (Div. 2) E:Riding in a Lift DP + 前缀优化

题意: n,a,b,k(2?≤?n?≤?5000,1?≤?k?≤?5000,1?≤?a,?b?≤?n,a?≠?b).四个数.1到n的数,顺序排列,其实位置人在a位置而中心位置在b,人每次只能走一个点走动的距离必须小于|b?a|,人走k步之后停止,问人一共有多少种走法. 分析: 开始很容易想到一个深度优先搜索实现递归方法dfs(a, k)但k变为0就到达搜索底部,这样时间复杂度是O(nk)显然非常不好. 然后可以想到会有重算的情况,就可以加一个记忆优化把算过的(a,k)的二元组都保存下来.这样处理

CF 479E Riding in a Lift 前缀和 DP

输入 n a b k 有n层楼 起点在a层 b层是不能到达的 假设当前在x层 每一次可以到达y层 满足 |x-y| < |x-b| 求进行k次的不同方案数 dp[i][j]为第i次到达j层的方案数 dp[i][j] = sum(dp[i-1][k])  其中|k-j| < |k-b| 满足条件的k是连续的一段 用前缀和优化 #include <cstdio> #include <cstring> #include <cstdlib> using namesp

Codeforces Round #274 Div.1 C Riding in a Lift --DP

题意:给定n个楼层,初始在a层,b层不可停留,每次选一个楼层x,当|x-now| < |x-b| 且 x != now 时可达(now表示当前位置),此时记录下x到序列中,走k步,最后问有多少种可能的数的序列. 解法: 定义:      dp[i][j] 表示第i步在j楼的不同序列的个数 转移方程: 当j<b时, 那么dp[i][j] += dp[i-1][0~(j与b的中点(以下))] 当j>b时, 那么dp[i][j] += dp[i-1][(j与b的中点(以下))~n] 由于dp[

CF R274 Div2 E Riding in a Lift DP

先预处理出能到当前点的区间,然后通过前缀和求得当前值即可. #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <map> #include <set> #include <climits> #include <iostream> #include &

CodeForces 540D Bad Luck Island 概率dp

CodeForces 540D 应该是简单概率dp,由于写得少显得十分蠢萌 求期望逆推,求概率正推,大概是这么个意思,贴一发留恋 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define db double const int maxn=108; db dp[maxn][maxn][maxn]; int main() { int i,j,n,m,k,p; whi

codeforces 148E Aragorn&#39;s Story 背包DP

Aragorn's Story Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/problem/148/E Description Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who