扫雷 HDU - 5965 (dp,左右相互影响,但是有固定的起点)

扫雷游戏是晨晨和小璐特别喜欢的智力游戏,她俩最近沉迷其中无法自拔。 
该游戏的界面是一个矩阵,矩阵中有些格子中有一个地雷,其余格子中没有地雷。 游戏中,格子可能处于己知和未知的状态。如果一个己知的格子中没有地雷,那么该 格子上会写有一个一位数,表示与这个格子八连通相邻的格子中地雷总的数量。 
现在,晨晨和小璐在一个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

题意:扫雷小游戏,3*n的矩形,中间的一行全是数字,表示周围的雷数,求有多少种的雷的分布方案。

思路:放地雷时,每一列最多放两个,相邻的相互影响;刚开始看到这道题无从下手,看着像dp,但是找不到递推式

这道题的重点是,看到有固定起点或终点,从起点开始,起点的个数确定了,那么后面每一列格子的个数也就确定了

,从前往后推,前一列的个数确定后列的个数,到最后看看最后两列的地雷的个数看看和题目上要求最后一列的地雷

个数是否相等; 递推式 dp[j] = a[j-1] - dp[j-1] - dp[j-2];

先枚举第一个列的地雷个数;

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define Max 10010
#define ll long long 
#define mod 100000007
char str[Max];
int a[Max];

int dp[Max];
int main()
{
	int i,j,t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%s",str);
		int l = strlen(str);
		for(i = 0;i<l;i++)
			a[i] = str[i] - '0';
		if(l==1)  // 因为下标我是从0开始的,所以当l==1时,下面的程序不能判断dp[0]中就是a[0]个; 
		{
			if(a[0]==0||a[0]==2) printf("1\n");
			else if(a[0]==1) printf("2\n");
			else printf("0\n");
			continue;
		}
		ll res,s = 0;
		for(i = 0;i<=a[0];i++)
		{
			if(i>2) break;
			dp[0] = i;
			res = 1;
			for(j = 1;j<l;j++)
			{
				int k;
				if(j==1) k = a[j-1] - dp[j-1];  
				else k = a[j-1] - dp[j-1] - dp[j-2];
				if(k<0||k>2)
					break;
				if(j==l-1&&a[j]!=k+dp[j-1])
					break;
				dp[j] = k;
			}
			if(j<l) continue;
			for(int k = 0;k<l;k++)
			{
				if(dp[k]==1)
					res = res*2%mod;
			}
			s= (s+res)%mod;	
		}
		printf("%lld\n",s);
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/obsorb_knowledge/article/details/80412238