BZOJ1088 [SCOI2005]扫雷Mine 动态规划
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1088
题意概括
扫雷。只有2行。第2行没有雷,第一行有雷。告诉你第二行显示的数组,问有几种摆放方式。
题解
动态规划。
用dp[i][0][0]表示当前位置为0,前一位置为0的方案总数,
用dp[i][0][1]表示当前位置为1,前一位置为0的方案总数,
用dp[i][1][0]表示当前位置为0,前一位置为1的方案总数,
用dp[i][1][1]表示当前位置为1,前一位置为1的方案总数,
然后分各种情况转移即可。
网上又说直接模拟的——代码比我短好多!都是大佬!Orz
代码
#include <cstring> #include <algorithm> #include <cstdlib> #include <cmath> #include <cstdio> using namespace std; typedef long long LL; const int N=10000+5; int n,a[N]; LL dp[N][2][2]; int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=n;i++) if (a[i]>3) {printf("0");return 0;} if (a[1]>2||a[n]>2) {printf("0");return 0;} memset(dp,0,sizeof dp); if (a[1]==0) dp[1][0][0]=1; else if (a[1]==1) dp[1][0][0]=dp[1][0][1]=1; else if (a[1]==2) dp[1][0][1]=1; for (int i=2;i<=n;i++){ int v=a[i-1]; LL p00=dp[i-1][0][0],p01=dp[i-1][0][1],p10=dp[i-1][1][0],p11=dp[i-1][1][1]; LL &n00=dp[i][0][0],&n01=dp[i][0][1],&n10=dp[i][1][0],&n11=dp[i][1][1]; if (a[i]==0){ if (v>1) {printf("0");return 0;} if (v==1) n00+=p10; else if (v==0) n00+=p00; } else if (a[i]==1){ if (v==3) {printf("0");return 0;} if (v==2) n10+=p11,n01+=p10; else if (v==1) n10+=p01,n01+=p00,n00+=p10; else if (v==0) n00+=p00; } else if (a[i]==2){ if (v==0) {printf("0");return 0;} if (v==1) n01+=p00,n10+=p01; else if (v==2) n11+=p01,n10+=p11,n01+=p10; else if (v==3) n11+=p11; } else if (a[i]==3){ if (v<2) {printf("0");return 0;} if (v==2) n11+=p01; else n11+=p11; } } LL ans; if (a[n]==0) ans=dp[n][0][0]; else if (a[n]==1) ans=dp[n][0][1]+dp[n][1][0]; else ans=dp[n][1][1]; printf("%lld",ans); return 0; }