动态规划例题

走路

题目描述

有一条很长的数轴,一开始你在0的位置。接下来你要走n步,第i步你可以往右走ai或者bi。
问n步之后,0到m的每个位置,能不能走到?

输入格式

第一行,两个整数n,m。
接下来n行,每行两个整数ai,bi。

输出格式

一行,一共m+1个数,每个数都是0或1表示能否走到,数字之间不用空格隔开。

样例输入
3 10
1 2
2 6
3 3
样例输出
00000011001
思路

输出要求是走到最后一步之后, 可以走到的所有位置,如果最后一步走到了位置i,那么倒数第二步就需要走到i-a或者i-b,所以就考虑动态规划,用布尔数组来表示是否能走到i的位置,而每次转移就是考虑i-a或者i-b能不能走到,依次从后往前推到,这里的思路类似于走楼梯

动态规划代码
#include<iostream>

using namespace std;

const int N = 100010;

int n, m;
bool st[110][N];

int main()
{
    cin >> n >> m;
    st[0][0] = true;
    for ( int i = 1; i <= n; i ++ )
    {
        int a, b;
        cin >> a >> b;
        if (a > b) swap(a, b);
        for ( int j = m; j >= a; j -- )
        {
            st[i][j] |= st[i - 1][j - a];
            if (j >= b) st[i][j] |= st[i - 1][j - b];
        }
    }

    for ( int i = 0; i <= m; i ++ )
    {
        if (st[n][i]) cout << "1";
        else cout << "0";
    }

    return 0;
}

走楼梯变形(最多连续三次走2级台阶)

题目描述

楼梯有 n 阶,上楼可以一步上一阶,也可以一步上二阶。
但你不能连续三步都走两阶,计算走到第n阶共有多少种不同的走法。

输入格式

一行,一个数字,表示n。

输出格式

输出走楼梯的方式总数。

输入样例
6
输出样例
12
思路

n最大100,dfs时间复杂度为O(2^100),铁定tle(亲测)
动态规划思路:二维数组来记录,一维记录当前所在位置,二维记录前面已经有了连续几次2步,题目限制原因,二维只需要考虑0,1,2,所以数组开dp[N][3],因为要用的i-2,所以千万要记得在循环之前把1和2处理出来,然后进行循环即可

代码
#include<iostream>

using namespace std;

long long f[60][3];

int main()
{
    int n;
    cin >> n;
    f[0][0] = 1;
    f[1][0] = 1;

    for ( int i = 2; i <= n; i ++ )
    {
        f[i][0] = f[i - 1][0] + f[i - 1][1] + f[i - 1][2];
        f[i][1] = f[i - 2][0];
        f[i][2] = f[i - 2][1];
    }

    cout << f[n][0] + f[n][1] + f[n][2] << endl;

    return 0;
}
posted @ 2022-02-28 21:59  NUC_ACM开完刀  阅读(219)  评论(0编辑  收藏  举报