cf404 D. Minesweeper 1D(dp后效性,分类讨论)
作者:互联网
题意:
一维扫雷游戏,*
表示有雷,0/1/2
表示周围有几个雷。棋盘上的一些位置已知,一些位置未知(用?
表示),求合法的棋盘数。
思路:
有一点点后效性,讨论就完事了。
\(f[i][state]\),\(state\) 为第 \(i\) 个位置的状态:0左右没雷,1左边有雷右边没雷,2左边没雷右边有雷,3左右有雷,4这里有雷但对左右无要求。(状态0~3都是这里没雷)
\(s[i]=*\implies f[i][4]=f[i-1][2]+f[i-1][3]+f[i-1][4]\)
\(s[i]=0\implies f[i][0]=f[i-1][0]+f[i-1][1]\)
\(s[i]=2\implies f[i][3]=f[i-1][4]\)
\(s[i]=1\implies f[i][1]=f[i-1][4],f[i][2]=f[i-1][0]+f[i-1][1]\)
初值:不妨假设 \(-1\) 位置没雷,\(0\) 位置没雷, \(1\) 位置可能有雷也可能没雷。则 \(f[0][0]=f[0][2]=1\)
(当然也可以设 \(-1\) 有雷,\(0\) 还是没雷,则 \(f[0][1]=f[0][3]=1\))
答案:第 \(n+1\) 位没雷,所以答案是 \(f[n][0]+f[n][1]+f[n][4]\)
const int N = 1e6 + 5, MOD = 1e9 + 7;
ll n, f[N][6];
char s[N];
signed main()
{
cin >> (s + 1); n = strlen(s + 1);
f[0][0] = f[0][2] = 1;
for(int i = 1; i <= n; i++)
{
if(s[i] == '*' || s[i] == '?')
f[i][4] = (f[i-1][2] + f[i-1][3] + f[i-1][4]) % MOD;
if(s[i] == '0' || s[i] == '?')
f[i][0] = (f[i-1][0] + f[i-1][1]) % MOD;
if(s[i] == '2' || s[i] == '?')
f[i][3] = f[i-1][4];
if(s[i] == '1' || s[i] == '?')
f[i][1] = f[i-1][4], f[i][2] = (f[i-1][0] + f[i-1][1]) % MOD;
}
cout << (f[n][0] + f[n][1] + f[n][4]) % MOD;
}
标签:后效,cf404,implies,int,Minesweeper,位置,有雷,没雷 来源: https://www.cnblogs.com/wushansinger/p/15863996.html