洛谷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\n",f[n-1][1]+f[n-1][2]); 47 if(w[n]==2)printf("%d\n",f[n-1][3]); 48 if(w[n]==3)printf("0\n"); 49 if(w[n]==0)printf("%d\n",f[n-1][0]); 50 return 0; 51 }
本文为博主原创文章,转载请注明出处。