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[i][j]的值只跟dp[i-1][]的一些值有关,所以用滚动数组会大大减小内存。

用一个sum[i][j]维护前缀和即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#define Mod 1000000007
#define lll __int64
using namespace std;
#define N 100007

lll dp[2][5002],sum[2][5002];
int n;

int main()
{
    int a,b,k,i,j;
    while(cin>>n>>a>>b>>k)
    {
        memset(dp,0,sizeof(dp));
        memset(sum,0,sizeof(sum));
        dp[0][a] = 1LL;
        for(i=a;i<=n;i++)
            sum[0][i] = 1LL;
        int now = 0;
        for(i=1;i<=k;i++)
        {
            now ^= 1;
            memset(dp[now],0,sizeof(dp[now]));
            memset(sum[now],0,sizeof(sum[now]));
            for(j=1;j<=n;j++)
            {
                if(j < b)
                {
                    int k = (j+b-1)/2;
                    dp[now][j] = (dp[now][j]+sum[now^1][k]-dp[now^1][j])%Mod;
                }
                else if(j > b)
                {
                    int k = (j+b+2)/2;
                    dp[now][j] = (dp[now][j]+sum[now^1][n]-sum[now^1][k-1]-dp[now^1][j])%Mod;
                }
                sum[now][j] = (sum[now][j-1]+dp[now][j])%Mod;
            }
        }
        lll sum = 0;
        for(i=1;i<=n;i++)
            sum = (sum+dp[now][i])%Mod;
        cout<<(sum+Mod)%Mod<<endl;
    }
    return 0;
}

时间: 2024-08-25 14:34:29

Codeforces Round #274 Div.1 C Riding in a Lift --DP的相关文章

Codeforces Round #274 (Div. 2) E. Riding in a Lift(DP)

Imagine that you are in a building that has exactly n floors. You can move between the floors in a lift. Let's number the floors from bottom to top with integers from 1 to n. Now you're on the floor number a. You are very bored, so you want to take t

Codeforces Round #267 (Div. 2) C. George and Job(DP)补题

Codeforces Round #267 (Div. 2) C. George and Job题目链接请点击~ The new ITone 6 has been released recently and George got really keen to buy it. Unfortunately, he didn't have enough money, so George was going to work as a programmer. Now he faced the follow

Codeforces Round #433 (Div. 1) D. Michael and Charging Stations(dp)

题目链接:Codeforces Round #433 (Div. 1) D. Michael and Charging Stations 题意: 一个人每天要加油,1种为1000,1种为2000,如果付全额,会得到10%的回扣放在卡上. 如果卡上有剩余的回扣,可以拿来抵现金.问n天最少需要花多少钱. 题解: 很直观的一个dp就是考虑dp[i][j],表示第i天卡上剩余回扣为j的最小花费. 将所有的数除以100后,j其实是小于40的,严格的说是小于30,官方题解有个证明. 因为卡上不可能积累很多的

Codeforces Round #419 (Div. 2) E. Karen and Supermarket(树形DP)

题目链接:Codeforces Round #419 (Div. 2) E. Karen and Supermarket 题意: 有n件物品,每个物品有一个价格,和一个使用优惠券的价格,不过这个优惠券有一个限制,必须要在第x个使用后才可以使用.现在有m的钱,问最多能买多少个物品. 题解: 每个优惠券都只与一个券有关,所以根据这个关系就可以构成一棵树. 考虑树形dp,dp[i][j][k(0|1)]表示第i个节点所构成的子树中买了j个物品,使用优惠券和不使用优惠券的最少钱. 转移方程看代码详细解释

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)的二元组都保存下来.这样处理

codeforces水题100道 第八题 Codeforces Round #274 (Div. 2) A. Expression (math)

题目链接:http://www.codeforces.com/problemset/problem/479/A题意:给你三个数a,b,c,使用+,*,()使得表达式的值最大.C++代码: #include <iostream> using namespace std; int a, b, c, ans; int main() { cin >> a >> b >> c; int t = max(a+b, a*b); ans = max(t + c, t * c

Codeforces Round #274 (Div. 2) B. Towers

As you know, all the kids in Berland love playing with cubes. Little Petya has n towers consisting of cubes of the same size. Tower with number i consists of ai cubes stacked one on top of the other. Petya defines the instability of a set of towers a

Codeforces Round #274 (Div. 2) C. Exams

Student Valera is an undergraduate student at the University. His end of term exams are approaching and he is to pass exactly n exams. Valera is a smart guy, so he will be able to pass any exam he takes on his first try. Besides, he can take several

Codeforces Round #274 (Div. 2)

A. Expression 题意:给出a,b,c,给出"+","*",“()”在这三个数中任意放置这三个符号,求最大值 直接枚举6种情况就可以了,自己写的时候是挨个比找的最大值,后来发现别人的题解里面,直接将这6个值排序取最后一个数就可以了. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include