Hdu 5965 扫雷(dfs)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5965
解题思路:用num数组记录样例给出的数字,用dp数组记录每位的地雷数量,通过给出的第一位数字来枚举第一位可能的地雷数,然后第二位的地雷数就能确定了,一定是num[0]-dp[0],(0为第一位的下标),因为扫雷标记的数字只会是8方向的格子,但是第一位影响的到的只有自己这格子和右边这个格子,那么第一位的地雷数确定了,第二位的地雷数也就能确定了,(枚举中会出现不合法的情况,即地雷数不在0到2直接,直接跳出就行,最后一位也要判断一下地雷数对不对),之后的每一位就受到前两位的影响,就是前两位确定了地雷数,在拿前一位的num值减去就是地雷数,如果推到底了都没问题,就开始计数(用初值为1的res表示),而每一位的地雷摆放,只有当他数量为一的时候能有两种可能,即上或者下,(遇到1的情况res*2%mod即可(注意:mod为1e8+7)),算完res,给sum加上res在取模即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
#define MAXN 10005
char c[MAXN];
int num[MAXN];
typedef long long ll;
const ll mod=1e8+7;
ll dp[MAXN],sum;
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%s",c);
int n=strlen(c);
for(int i=0;i<n;i++){
num[i]=c[i]-'0';
}
sum=0;
for(int i=0;i<=num[0]&&i<=2;i++){//枚举dp[0]的可能性
dp[0]=i;
dp[1]=num[0]-dp[0];//第一位的地雷数会等于数字和第0位地雷数之差,因为第零位数字剩下的只能在第一位
if(dp[1]>2||dp[1]<0)continue;//判断合不合法,地雷数一定在0到2之间
bool flag=true;
for(int j=2;j<n;j++){
dp[j]=num[j-1]-dp[j-1]-dp[j-2];
if(dp[j]>2||dp[j]<0){//不可能的地雷数
flag=false;
break;
}
}
if(dp[n-2]+dp[n-1]!=num[n-1]){//最后的地雷数不对,那就不是答案
flag=false;
}
if(flag){
ll res=1;
for(int j=0;j<n;j++){
if(dp[j]==1)res=(res*2)%mod;//只有地雷数为1时才有摆放的可能,0和2都只有固定位置
}
sum=(sum+res)%mod;
}
}
printf("%lld\n",sum);
}
return 0;
}