题目描述
相信大家都玩过扫雷的游戏。那是在一个n\times mn×m的矩阵里面有一些雷,要你根据一些信息找出雷来。万圣节到了,“余”人国流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子没有雷,那么它里面的数字表示和它8连通的格子里面雷的数目。现在棋盘是n\times 2n×2的,第一列里面某些格子是雷,而第二列没有雷,如下图:
由于第一列的雷可能有多种方案满足第二列的数的限制,你的任务即根据第二列的信息确定第一列雷有多少种摆放方案。
输入输出格式
输入格式:
第一行为N,第二行有N个数,依次为第二列的格子中的数。(1<= N <= 10000)
输出格式:
一个数,即第一列中雷的摆放方案数。
输入输出样例
输入样例#1
2 1 1
输出样例#1
2
思路
可以不考虑dp,用dfs的话会把问题简单化。
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
int a[10002],b[10002],n,s,cnt;//s
void dfs(int i)
{
s=0;//s累计a[i]周围的雷数
if(b[i]!=0) s++;//如果当前的点是雷
if(b[i-1]!=0) s++;//如果上面一个点是雷
if(a[i]-1==s)//如果a[i]是3,说明下面的一个点可能是雷
{
if(i+1>n)//越过边界还是狗带吧
{
return;
}
b[i+1]=1;//标记下一个点会是雷
dfs(i+1);//从下一个点开始搜索
b[i+1]=0;//回溯,很重要,我们是寻找算符种数
return;
}
if(a[i]!=s)//当前a[i]与周围雷数不匹配,肯定就错了
{
return;
}
if(i==n)//到达边界
{
cnt++;
return;
}
dfs(i+1);
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
register int i,j,k;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i];
}
b[1]=1;//设第1个格子是有雷的
dfs(1);//从点1开始搜索
memset(b,0,sizeof b);
dfs(1);//因为最上面第1个格子无法判断是不是雷,所以要搜第2次,这次的b[1]就是0,代表不是雷。
cout<<cnt<<endl;
return 0;
}