洛谷P2327 [SCOI2005] 扫雷

题目描述

输入输出格式

输入格式:

第一行为N,第二行有N个数,依次为第二列的格子中的数。(1<= N <= 10000)

输出格式:

一个数,即第一列中雷的摆放方案数。

输入输出样例

输入样例#1:
2
1  1
输出样例#1:
2

迷之DP,如果没看算法标签,可能会想岔到数学方向。

一个数字会影响它正左、左上、左下三个格子的方案。考虑左边和左上两个方向的地雷数,可以推出左下是否有雷。

然而这样考虑,决策似乎是有后效性的。改为枚举左上情况,考虑左边和左下两个方向的雷数。

方程写了一长串……

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 using namespace std;
 9 const int mxn=10010;
10 int read(){
11     int x=0,f=1;char ch=getchar();
12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
14     return x*f;
15 }
16 int n;
17 int f[mxn][4];
18 int w[mxn];
19 //f[][0] 左边和左下没有雷
20 //f[][1] 仅左下有雷
21 //f[][2] 仅左边有雷 
22 //f[][3] 左边和左下有雷 
23 int main(){
24     n=read();
25     for(int i=1;i<=n;i++) w[i]=read();
26     if(w[1]==0){f[1][0]=1;}
27     else if(w[1]==1){f[1][1]=f[1][2]=1;}
28         else if(w[1]==2){f[1][3]=1;}
29     for(int i=2;i<n;i++){
30         if(w[i]==0)
31             f[i][0]=f[i-1][0];
32         if(w[i]==1){
33             f[i][0]+=f[i-1][2];
34             f[i][1]+=f[i-1][0];
35             f[i][2]+=f[i-1][1];
36         }
37         if(w[i]==2){
38             f[i][1]+=f[i-1][2];
39             f[i][2]+=f[i-1][3];
40             f[i][3]+=f[i-1][1];
41         }
42         if(w[i]==3){
43             f[i][3]=f[i-1][3];
44         }
45     }
46     if(w[n]==1)printf("%d
",f[n-1][1]+f[n-1][2]);
47     if(w[n]==2)printf("%d
",f[n-1][3]);
48     if(w[n]==3)printf("0
");
49     if(w[n]==0)printf("%d
",f[n-1][0]);
50     return 0;
51 }
原文地址:https://www.cnblogs.com/SilverNebula/p/6051094.html