思路:状态机dp
我们知道了三个状态,就是吃1号外卖,2号外卖和3号外卖。
这样做的目的就是为了区分是不是连续吃了同一家外卖了,就不用额外的去判断这个条件了,直接就可以算出来。
一开始的思路其实是照着爬楼梯的哪个思路来的,后来发现,其实爬楼梯的那个状态和这道题并没有什么关系可说。也就是说,爬楼梯的设置状态在这道题上毫无转移关系,所以就撇除了。
并不知道怎么做,其他的动态规划题型也不像,最后才把眼光放到了状态机上。
代码思路如下:dp[i][j]表示在第i天吃j号外卖的方案数。
那么:假设我们在第i天吃了1号外卖,那么我们在I-1天的时候吃了2号外卖,那么i-2天可以随便吃,同理i-1天吃了3号外卖在后续也是可以随便吃;
但是当我们i-1天吃了1号外卖的时候,i-2天就不能吃1号外卖了,而是选择2号和3号外卖其中一个吃。(题目要求)
总体下来就是这样的状态方程:dp[i][1]=dp[i-1][2]+dp[i-1][3]+(dp[i-2][2]+dp[i-2][3])(这个括号里面表示就是在i-1天吃1号外卖的时候的情况)以此类推就行了。
上代码:
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
#include<deque>
#include <iomanip>
#include<sstream>
#include<numeric>
#include<map>
#include<limits.h>
#include<unordered_map>
#include<set>
#define int long long
#define MAX 100010
#define inf 0x3f3f3f3f
#define _for(i,a,b) for(int i=a;i<(b);i++)
using namespace std;
typedef pair<int, int> PII;
int n,m;
int counts,u=1;
int dx[] = { 0,1,0,-1};
int dy[] = { 1,0,-1,0 };
int dp[MAX][3];
int mod = 1e9 + 7;signed main() {ios::sync_with_stdio(false);cin.tie(NULL); cout.tie(NULL);cin >> n;while (n--) {cin >> m;memset(dp, 0, sizeof dp);dp[1][1] = dp[1][2] = dp[1][3] = 1;dp[2][1] = dp[2][2] = dp[2][3] = 3;for (int i = 3; i <= 100010; i++) {dp[i][1] = ((dp[i - 1][2] + dp[i - 1][3]) % mod + dp[i - 2][2] + dp[i - 2][3]) % mod;dp[i][2] = ((dp[i - 1][1] + dp[i - 1][3]) % mod + dp[i - 2][1] + dp[i - 2][3]) % mod;dp[i][3] = ((dp[i - 1][1] + dp[i - 1][2]) % mod + dp[i - 2][1] + dp[i - 2][2]) % mod;}cout << ((dp[m][1] + dp[m][2]) % mod + dp[m][3]) % mod << endl;}return 0;
}