E - 扫雷 枚举+思维
链接: https://vjudge.net/contest/400079#problem/E
思路:假如在第一列的时候的雷的数量是确定的,那么接下来遍历过去,所有列的雷的个数都是可以确定的
所以我们在第一列枚举 0~min(2,a[1]),然后各自跑过去,去除非法情况
最后留下来的合法情况再这样计算:
当当前列的雷的个数是1是,乘2,否则乘1即可
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include <climits> 7 #include <cstring> 8 #include<sstream> 9 #include <string> 10 #include <set> 11 #include <map> 12 #include <queue> 13 #include <stack> 14 #include <vector> 15 #include <list> 16 #define rep(i,m,n) for(i=m;i<=n;i++) 17 #define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++) 18 const int Mod = 1e8 + 7; 19 using namespace std; 20 int dp[10005],num[10005]; 21 char s[10005]; 22 long long int sum,ans; 23 int main() 24 { 25 int T,l; 26 cin>>T; 27 getchar(); 28 while(T--){ 29 memset(dp,0,sizeof(dp)); 30 sum=0; //初始化 31 gets(s); 32 l=strlen(s); 33 for(int i=0;i<l;i++) 34 num[i+1]=s[i]-'0'; //将字符串转化为数字 35 for(int i=0;i<=num[1];i++) //枚举位置1上的情况 36 { 37 int flag=1; 38 ans=1; 39 if(i>2) break; //可能的情况0,1,2 40 dp[1]=i; 41 int j; 42 for(j=2;j<=l;j++){ 43 44 dp[j]=num[j-1]-dp[j-1]-dp[j-2]; 45 if(dp[j]>2||dp[j]<0) //可能的情况0,1,2 46 { 47 flag=0; 48 break; 49 } 50 51 } 52 if(j==l+1&&dp[l]+dp[l-1]!=num[l]) 53 flag=0; 54 //判断最后两列是否满足要求,(这里的判断不要放到前面的for循环里,我前面的循环从第二列开始,而它可能只有一列,这里的bug我找了半天。。。) 55 if(flag==1) 56 { 57 for(j=1;j<=l;j++) 58 { 59 if(dp[j]==1) ans=ans*2%Mod; //如果是0或2则只有一种可能,如果是1则有两种 60 } 61 sum=(sum+ans)%Mod; //将每次枚举得出的可能加到sum中 62 } 63 } 64 cout<<sum<<endl; //输出结果 65 } 66 return 0; 67 }