https://www.luogu.org/problem/show?pid=2327
借鉴了一位dalao(@xyz32768)(洛谷)的题解
设一个四维数组f[i][0/1][0/1][0/1],分别表示第i个,i-1个是否有地雷,i个是否有地雷,i+1个是否有地雷。
当a=0时(如图)
图1
此时只有一种情况:
也就是f[i][0][0][0]=f[i-1][0][0][0]+f[i-1][1][0][0]。
当a=1时,如下图所示:
此时,有三种情况:
即:
f[i][1][0][0]=f[i-1][0][1][0]+f[i-1][1][1][0]
f[i][0][1][0]=f[i-1][0][0][1]+f[i-1][1][0][1],
f[i][0][0][1]=f[i-1][0][0][0]+f[i-1][1][0][0]。
其他两种情况详见代码。
边界条件是f[0][0][0][0] = f[0][0][0][1] =1(这两种情况下都只有一种)
此外,结果取决于最后一个数字。如果该数字为0,说明答案是f[n][0][0][0];为1,则为f[n][1][0][0]与f[n][0][1][0]之和。其他两种情况见代码。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int f[10005][2][2][2];
inline int read(){
int res = 1,x = 0;
char ch = 0;
while(ch<'0'||ch>'9'){
if (ch=='-')
res = -1;
ch = getchar();
}
while(ch>='0'&&ch<='9'){
x = (x<<3) + (x<<1) + ch - 48;
ch = getchar();
}
return x*res;
}
int main(){
int n = read();
int a;
f[0][0][0][0] = f[0][0][0][1] = 1;
for (int i =1;i<=n;i++){
a = read();
switch(a){
case 0:
f[i][0][0][0] = f[i-1][0][0][0] + f[i-1][1][0][0];
break;
case 1:
f[i][1][0][0] = f[i-1][0][1][0] + f[i-1][1][1][0];
f[i][0][1][0] = f[i-1][0][0][1] + f[i-1][1][0][1];
f[i][0][0][1] = f[i-1][0][0][0] + f[i-1][1][0][0];
break;
case 2:
f[i][1][1][0] = f[i-1][0][1][1] + f[i-1][1][1][1];
f[i][1][0][1] = f[i-1][0][1][0] + f[i-1][1][1][0];
f[i][0][1][1] = f[i-1][0][0][1] + f[i-1][1][0][1];
break;
case 3:
f[i][1][1][1] = f[i-1][0][1][1] + f[i-1][1][1][1];
break;
}
}
int ans;
if (a == 0) ans = f[n][0][0][0];
if (a == 1) ans = f[n][1][0][0] + f[n][0][1][0];
if (a == 2) ans = f[n][1][1][0];
if (a == 3) ans = 0;
cout<<ans<<endl;
return 0;
}