非 常 水 的 一 道 题 非常水的一道题 非常水的一道题
发现第 i i i个位置与第 i − 1 i-1 i−1和 i + 1 i+1 i+1有关
所以直接暴力思维 d p dp dp带着所有状态冲就是了
定义 d p [ i ] [ j ] [ q ] [ w ] dp[i][j][q][w] dp[i][j][q][w]为 d p dp dp到第 i i i位时
i − 1 i-1 i−1位是否有火 ( j ) (j) (j), i i i位置是否有火 ( q ) (q) (q), i + 1 i+1 i+1位置是否有火 ( w ) (w) (w)
#include <bits/stdc++.h> using namespace std; #define int long long const int maxn=1e6+10; const int mod=1e9+7; int n,m,dp[maxn][2][2][2]; char a[maxn]; signed main() { cin >> (a+1); n=strlen(a+1); dp[0][0][0][0]=dp[0][0][0][1]=1; for(int i=1;i<=n;i++) { if( a[i]=='0' ) dp[i][0][0][0]=dp[i-1][1][0][0]+dp[i-1][0][0][0]; else if( a[i]=='1' ) { dp[i][0][0][1]=dp[i-1][1][0][0]+dp[i-1][0][0][0]; dp[i][1][0][0]=dp[i-1][1][1][0]+dp[i-1][0][1][0]; } else if( a[i]=='2' ) dp[i][1][0][1]=dp[i-1][1][1][0]+dp[i-1][0][1][0]; else if( a[i]=='*' ) { for(int j=0;j<=1;j++) for(int q=0;q<=1;q++) dp[i][j][1][q]=dp[i-1][0][j][1]+dp[i-1][1][j][1]; } else { for(int j=0;j<=1;j++) for(int q=0;q<=1;q++) for(int w=0;w<=1;w++) dp[i][j][q][w]=dp[i-1][0][j][q]+dp[i-1][1][j][q]; } for(int j=0;j<=1;j++) for(int q=0;q<=1;q++) for(int w=0;w<=1;w++) dp[i][j][q][w]%=mod; } int ans=0; for(int i=0;i<=1;i++) for(int j=0;j<=1;j++) ans = (ans+dp[n][i][j][0] )%mod; cout << ans; }但是似乎可以优化掉一维
因为转移的时候 i − 1 i-1 i−1是用不到的
在转移状态 i i i时,只需要 i − 1 i-1 i−1的起火状态和 i i i的起火状态
实际上只需要 d p [ i ] [ q ] [ w ] dp[i][q][w] dp[i][q][w]即可