DP基础练习1

题面:

有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法?

Input

输入数据首先包含一个整数N,表示测试实例的个数,然后是N行数据,每行包含一个整数M(1<=M<=40),表示楼梯的级数。

Output

对于每个测试实例,请输出不同走法的数量

Sample Input

2
2
3

Sample Output

1
2

思路: 

dp[1]=0;

dp[2]=1;

dp[3]=2;

转移方程:dp[M]=dp[M-1]+dp[M-2]

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
using namespace std;
const int N=200;
int dp[50];
void solve()
{
    dp[1]=0;
    dp[2]=1;
    dp[3]=2;
    for(int i=4;i<=40;i+=1){
        dp[i]=dp[i-1]+dp[i-2];
    }
}
int main()
{
    solve();
    //printf("%d\n",dp[40]);
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        printf("%d\n",dp[n]);
    }
    return 0;
}

 

题面:

  某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹. 
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统. 

Input

  输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔) 

Output

  对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统. 

Sample Input

8 389 207 155 300 299 170 158 65

Sample Output

2

思路:飞来第i颗导弹时,看现有的系统能否将其拦截。若某一系统能拦截,则更新该系统最高能拦截的导弹高度(dp[index]=height[i]),若不能,则多配备一套系统,该系统目前最高能拦截的导弹高度为第i颗导弹的高度。

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
using namespace std;
const int N=1e4+5;
int dp[N],x[N],y;
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;++i){
            scanf("%d",&x[i]);
        }
        dp[0]=x[1];
        int Count=1;
        for(int i=1;i<=n;++i){
            for(y=0;y<Count;++y){
                if(x[i]<=dp[y])
                {
                    dp[y]=x[i];
                    break;
                }
            }
            if(y>=Count)
            {
                dp[y]=x[i];
                Count+=1;
            }
        }
        printf("%d\n",Count);
    }
    return 0;
}

 

题面:

在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 

有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少? 
 
已经告诉你了,这是个DP的题目,你能AC吗?

Input

输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。 

Output

对于每个测试实例,输出可能得到的最大和,每个实例的输出占一行。 

Sample Input

1
5
7
3 8
8 1 0 
2 7 4 4
4 5 2 6 5

Sample Output

30

思路:其实树塔就是一棵树,可以对每一层的节点编号,顺序为从上到下,从左到右。找一条从树根到叶子节点并且所有节点价值和最大的路径,可以自下而上对每个父节点更新其最优值( max { (cur[father]+dp[child1] , cur[father]+dp[child2] ) } )

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
using namespace std;
const int N=1e4+5;
int cur[N],dp[N];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        int node=0;
        for(int i=1;i<=n;i+=1){
            for(int y=1;y<=i;y+=1){
                int x;
                scanf("%d",&x);
                node+=1;
                cur[node]=x;
            }
        }
        memset(dp,0,sizeof(dp));
        for(int i=node;i>node-n;i--)
            dp[i]=cur[i];
        node-=n;
        for(int i=n-1;i>=1;i--){
            for(int y=1;y<=i;y+=1){
                dp[node]=max(dp[node+i]+cur[node],dp[node+i+1]+cur[node]);
                node--;
            }
        }
        printf("%d\n",dp[1]);
    }
    return 0;
}

 

题面:

A frog lives on the axis Ox and needs to reach home which is in the point n. She starts from the point 1. The frog can jump to the right at a distance not more than d. So, after she jumped from the point x she can reach the point x + a, where a is an integer from 1 to d.

For each point from 1 to n is known if there is a lily flower in it. The frog can jump only in points with a lilies. Guaranteed that there are lilies in the points 1and n.

Determine the minimal number of jumps that the frog needs to reach home which is in the point n from the point 1. Consider that initially the frog is in the point 1. If the frog can not reach home, print -1.

Input

The first line contains two integers n and d (2 ≤ n ≤ 100, 1 ≤ d ≤ n - 1) — the point, which the frog wants to reach, and the maximal length of the frog jump.

The second line contains a string s of length n, consisting of zeros and ones. If a character of the string s equals to zero, then in the corresponding point there is no lily flower. In the other case, in the corresponding point there is a lily flower. Guaranteed that the first and the last characters of the string s equal to one.

Output

If the frog can not reach the home, print -1.

In the other case, print the minimal number of jumps that the frog needs to reach the home which is in the point n from the point 1.

Examples

Input

8 4
10010101

Output

2

Input

4 2
1001

Output

-1

Input

8 4
11100101

Output

3

Input

12 3
101111100101

Output

4

Note

In the first example the from can reach home in two jumps: the first jump from the point 1 to the point 4 (the length of the jump is three), and the second jump from the point 4 to the point 8 (the length of the jump is four).

In the second example the frog can not reach home, because to make it she need to jump on a distance three, but the maximum length of her jump equals to two.

题意: 在一个一维坐标轴上,青蛙从位置1出发,要到达位置n。每步最多能走d个单位,问到位置n需要的最少步数是多少?

有一个限制条件,要想到达位置k,k位置上的对应字符需是‘1’。

思路:

不断更新从位置x -> y所需的最少步数

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
using namespace std;
const int N=1e4+5;
int x[N],dp[N];
char str[N];
int main()
{
    int n,d;
    while(~scanf("%d%d",&n,&d))
    {
        scanf("%s",str+1);
        if(str[1]=='0')
        {
            printf("-1\n");
            continue;
        }
        for(int i=1;i<=n;i+=1){
            dp[i]=N;
        }
        dp[1]=0;
        for(int p=1;p<n;p+=1)
        {
            for(int s=1;s<=d;s+=1)
            {
                if(s+p>n) break;
                if(str[s+p]=='1')
                    dp[p+s]=min(dp[p+s],dp[p]+1);
            }
            //printf("%d\n",dp[p]);
        }
        if(dp[n]==N)
            printf("-1\n");
        else
            printf("%d\n",dp[n]);
    }
    return 0;
}

 

题面:

In Python, code blocks don't have explicit begin/end or curly braces to mark beginning and end of the block. Instead, code blocks are defined by indentation.

We will consider an extremely simplified subset of Python with only two types of statements.

Simple statements are written in a single line, one per line. An example of a simple statement is assignment.

For statements are compound statements: they contain one or several other statements. For statement consists of a header written in a separate line which starts with "for" prefix, and loop body. Loop body is a block of statements indented one level further than the header of the loop. Loop body can contain both types of statements. Loop body can't be empty.

You are given a sequence of statements without indentation. Find the number of ways in which the statements can be indented to form a valid Python program.

Input

The first line contains a single integer N (1 ≤ N ≤ 5000) — the number of commands in the program. N lines of the program follow, each line describing a single command. Each command is either "f" (denoting "for statement") or "s" ("simple statement"). It is guaranteed that the last line is a simple statement.

Output

Output one line containing an integer - the number of ways the given sequence of statements can be indented modulo 109 + 7.

Examples

Input

4
s
f
f
s

Output

1

Input

4
f
s
f
s

Output

2

Note

In the first test case, there is only one way to indent the program: the second for statement must be part of the body of the first one.

simple statement
for statement
    for statement
        simple statement

In the second test case, there are two ways to indent the program: the second for statement can either be part of the first one's body or a separate statement following the first one.

for statement
    simple statement
    for statement
        simple statement

or

for statement
    simple statement
for statement
    simple statement

题意:python 里面,给出 n 个 for 循环或陈述语句,’f’ 里面必须要有语句。要求按 python 缩进的方式组合成合法的程序,最后一行一定为陈述。问有多少种可能方案。

思路:

dp[i][j]意义:第i行缩进j的方案数

当第i行语句为'f',第i+1行语句一定缩进;缩进方案dp[i+1][j+1]=dp[i][j];

当第i行语句为's',第i+1行的语句缩进一定<=第i行的缩进;缩进方案dp[i+1][j]=∑dp[i][k] (j<=k<=n-1)

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e3+5;
const ll Mod=1e9+7;
ll dp[N][N];
int main()
{
    int n;
    scanf("%d",&n);
    memset(dp,0,sizeof(dp));
    dp[1][0]=1;
    char c;
    ll s;
    for(int i=1;i<n;++i){
        cin>>c;
        if(c=='f')
        {
            for(int j=0;j<n;++j){
                dp[i+1][j+1]=dp[i][j];
            }
        }
        else
        {
            s=0;
            for(int j=n-1;j>=0;--j){
                s=(s+dp[i][j])%Mod;
                dp[i+1][j]=s;
            }
        }
    }
    cin>>c;
    s=0;
    for(int j=0;j<n;++j){
        s=(s+dp[n][j])%Mod;
    }
    printf("%lld\n",s);
    return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值