扫雷
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 985 Accepted Submission(s): 154
Problem Description
扫雷游戏是晨晨和小璐特别喜欢的智力游戏,她俩最近沉迷其中无法自拔。
该游戏的界面是一个矩阵,矩阵中有些格子中有一个地雷,其余格子中没有地雷。 游戏中,格子可能处于己知和未知的状态。如果一个己知的格子中没有地雷,那么该 格子上会写有一个一位数,表示与这个格子八连通相邻的格子中地雷总的数量。
现在,晨晨和小璐在一个3行N列(均从1开始用连续正整数编号)的矩阵中进 行游戏,在这个矩阵中,第2行的格子全部是己知的,并且其中均没有地雷;而另外 两行中是未知的,并且其中的地雷总数量也是未知的。
晨晨和小璐想知道,第1行和第3行有多少种合法的埋放地雷的方案。
该游戏的界面是一个矩阵,矩阵中有些格子中有一个地雷,其余格子中没有地雷。 游戏中,格子可能处于己知和未知的状态。如果一个己知的格子中没有地雷,那么该 格子上会写有一个一位数,表示与这个格子八连通相邻的格子中地雷总的数量。
现在,晨晨和小璐在一个3行N列(均从1开始用连续正整数编号)的矩阵中进 行游戏,在这个矩阵中,第2行的格子全部是己知的,并且其中均没有地雷;而另外 两行中是未知的,并且其中的地雷总数量也是未知的。
晨晨和小璐想知道,第1行和第3行有多少种合法的埋放地雷的方案。
Input
包含多组测试数据,第一行一个正整数T,表示数据组数。
每组数据由一行仅由数字组成的长度为N的非空字符串组成,表示矩阵有3行N 列,字符串的第i个数字字符表示矩阵中第2行第i个格子中的数字。
保证字符串长度N <= 10000,数据组数<= 100。
每组数据由一行仅由数字组成的长度为N的非空字符串组成,表示矩阵有3行N 列,字符串的第i个数字字符表示矩阵中第2行第i个格子中的数字。
保证字符串长度N <= 10000,数据组数<= 100。
Output
每行仅一个数字,表示安放地雷的方案数mod100,000,007的结果。
Sample Input
2 22 000
Sample Output
6 1
题目大意:
如题。
思路:
一开始想着如果我们固定第一列放 0 或者 1 或者 2 个雷的话,那么我们就能知道第二列雷的数量,然后我们就能知道第三列雷的数量。
可是我 突然一想,万一这个雷这样放不合适怎么办? 然后就卡住了。。。。就卡住了。。。
后来就想着对于这些雷的状态进行 dp 吧。 我就假设 dp [ i ] [ k ] 是 第 i 列放 k 颗雷 的方案数。
那么我们的状态转移方程如何写那?
dp [ i + 1 ] [ k ] = dp [ i -1 ] [ t ] + dp [ i -2 ] [ v ] ;
并且 k + t + v = 第 i 列的那个数字。
t k v 都要小于 等于 2 已经验证 这种思想是错误的。
因为 状态重复计算了。
AC代码L
#include<bits/stdc++.h>
using namespace std;
char ss[10005];
int dp[10005];
int a[10005];
int main()
{
int n;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",ss);
n=strlen(ss);
for(int i=0;i<n;i++)
{
a[i+1]=ss[i]-'0';
}
dp[0]=0;
int work;
int tt;
long long int ans=1;
long long int fans=0;
for(int i=0;i<=2&&i<=a[1];i++)
{
dp[1]=i;
work=0;
ans=1;
for(int j=2;j<=n;j++)
{
tt=a[j-1]-(dp[j-1]+dp[j-2]);
if(tt<0||tt+dp[j-1]>a[j]||tt>2)
{
work=1;
break;
}
dp[j]=tt;
}
if(!work&&dp[n-1]+dp[n]==a[n])
{
for(int j=1;j<=n;j++)
{
if(dp[j]==1)
{
ans*=2;
}
ans%=100000007;
}
fans+=ans;
fans%=100000007;
}
}
cout<<fans<<endl;
}
}