2021-03-26-飞步实习-机试题-动态规划

1. 描述

牛客链接

牛牛有一个3*n的土地。这个土地有3行,n列。牛牛想在土地上种至少一朵花。为了花儿能够茁壮成长,每一朵花的上下左右四个方向不能有其他的花。问有多少种种花的方案。为防止答案过大,答案对1e9+7取模。

2. 分析

土地总共3行,那么就有 2 的 3 次方, 8种种树的方式:

000
001
010
100
011
101
110
111

要求上下左右不能有树,所以:

011
110
111

这三种不满足要求。

还剩下:

000
001
010
100
101

这五种状态。

又因为,当 n = 1 时,要求土地上种至少一朵花,所以 000,也不满足要求。但当 n=2 的时候,前一列是可以取000这种状态的,只要 n=2 这一列不取 000 这种状态就好了。因此,每一列其实都有5种状态。最后把得到的总状态数-1即可。

dp[0][i],dp[1][i],dp[2][i],dp[3][i],dp[4][i] 分别代表第 i 列的第01234种状态有多少种取法。
当 n = 1时,dp[0][0] = 1,dp[1][0] = 1, dp[2][0] = 1,dp[3][0] = 1,dp[4][0] = 1

共有 5 种取法 (最后还需要减去1)

当 n = 2 时,
此时dp[0][1]:共 50 0
0 0
0 0

0 1
0 0
0 0

0 0
0 1
0 0

0 0
0 0
0 1

0 1
0 0
0 1

此时dp[1][1]:共 3 种,有两种不行,如下
1 0
0 0
0 0

//1 1
//0 0
//0 0

1 0
0 1
0 0

1 0
0 0
0 1

//1 1
//0 0
//0 1

所有的都依次类推

3. 代码

class Solution {
public:
    int solve(int n) {
        int MOD = 1e9+7;
        vector<vector<long> > dp(5, vector<long>(n,0));
        for(int i = 0; i < 5; i++){
            dp[i][0] = 1;
        }
        
        for(int i = 1; i < n; i++){
           dp[0][i] = (dp[0][i - 1] + dp[1][i - 1] + dp[2][i - 1] + dp[3][i - 1] + dp[4][i - 1]) % MOD; // 000
           dp[1][i] = (dp[0][i - 1] + dp[2][i - 1] + dp[3][i - 1]) % MOD;                               // 001
           dp[2][i] = (dp[0][i - 1] + dp[1][i - 1] + dp[3][i - 1] + dp[4][i - 1]) % MOD;                // 010
           dp[3][i] = (dp[0][i - 1] + dp[1][i - 1] + dp[2][i - 1]) % MOD;                               // 100
           dp[4][i] = (dp[0][i - 1] + dp[2][i - 1]) % MOD;                                              // 101
        }
        
        return (dp[0][n - 1] + dp[1][n - 1] + dp[2][n - 1] + dp[3][n - 1] + dp[4][n - 1] - 1) % MOD;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值