扫雷

扫雷

扫雷游戏是晨晨和小璐特别喜欢的智力游戏,她俩最近沉迷其中无法自拔。

该游戏的界面是一个矩阵,矩阵中有些格子中有一个地雷,其余格子中没有地雷。 游戏中,格子可能处于己知和未知的状态。如果一个己知的格子中没有地雷,那么该 格子上会写有一个一位数,表示与这个格子八连通相邻的格子中地雷总的数量。

现在,晨晨和小璐在一个3行N列(均从1开始用连续正整数编号)的矩阵中进 行游戏,在这个矩阵中,第2行的格子全部是己知的,并且其中均没有地雷;而另外 两行中是未知的,并且其中的地雷总数量也是未知的。

晨晨和小璐想知道,第1行和第3行有多少种合法的埋放地雷的方案。

Input
包含多组测试数据,第一行一个正整数T,表示数据组数。

每组数据由一行仅由数字组成的长度为N的非空字符串组成,表示矩阵有3行N 列,字符串的第i个数字字符表示矩阵中第2行第i个格子中的数字。

保证字符串长度N <= 10000,数据组数<= 100。

Output
每行仅一个数字,表示安放地雷的方案数mod100,000,007的结果。

Sample Input
2
22
000

Sample Output
6
1

思路
这个题目的思考角度和我之前在cf上pipes思路很类似!(上次没做出来,这次也是o(╥﹏╥)o)
对于这道题目,一共有3行n列,我们可以从列的角度出发,每次一列一列的放地雷数量
我们令num[i]为第2行i列的周围地雷数量(即题目提供的)
令dp[i]来记录每一列的地雷数,那么我们有:
                  dp[i]=num[i-1]-dp[i-1]-dp[i-2]
因为地雷的数量是环环相扣的,我们可以枚举第一列的数量,就可以得到之后每一列的数量——
如果一列的数量为0或2,该列只有一种放地雷的可能;如果一列的数量为1,该列有上下两种可能

代码如下:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int mx=1e4+10;
const int mod=1e8+7;//老实说这个最坑,一般都是1e9+7

int dp[mx],num[mx];
char s[mx];//dp[i]=num[i-1]-dp[i-1]-dp[i-2]; 
ll ans,cnt;

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		ans=0;
		memset(dp,0,sizeof(dp));
		scanf("%s",s+1);
		int l=strlen(s+1);
                for(int i=1;i<=l;i++)
                 num[i]=s[i]-'0';
        
                for(int i=0;i<=2;i++)
                {
        	 if(i>num[1])//如果第一列数量少了,就跳出
        	 break;
        	
        	int j;
        	dp[1]=i;
        	for(j=2;j<=l;j++)
        	{
        	  int tmp=num[j-1]-dp[j-1]-dp[j-2];
        	  if(tmp>2||tmp<0)//要满足每一列都在0-2之间
        	  break;
        	  dp[j]=tmp;
                }
                if(j<=l)//如果不满足跳过
                continue;
            
               if(num[l]==dp[l]+dp[l-1])//最后还需要判断一下! 
	       { 
                 cnt=1;
                for(int i=1;i<=l;i++)
                {
                  if(dp[i]==1)
                  cnt=(cnt*2)%mod;
                }
                ans=(ans+cnt)%mod;
              }
        }
        printf("%lld\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值