扫雷

来源:互联网 发布:科瑞明软件 怎么样 编辑:程序博客网 时间:2024/06/01 10:18

扫雷

                                                                  Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
                                                                                     Total Submission(s): 1502    Accepted Submission(s): 413


Problem Description
扫雷游戏是晨晨和小璐特别喜欢的智力游戏,她俩最近沉迷其中无法自拔。
该游戏的界面是一个矩阵,矩阵中有些格子中有一个地雷,其余格子中没有地雷。 游戏中,格子可能处于己知和未知的状态。如果一个己知的格子中没有地雷,那么该 格子上会写有一个一位数,表示与这个格子八连通相邻的格子中地雷总的数量。
现在,晨晨和小璐在一个3行N列(均从1开始用连续正整数编号)的矩阵中进 行游戏,在这个矩阵中,第2行的格子全部是己知的,并且其中均没有地雷;而另外 两行中是未知的,并且其中的地雷总数量也是未知的。
晨晨和小璐想知道,第1行和第3行有多少种合法的埋放地雷的方案。
 

Input
包含多组测试数据,第一行一个正整数T,表示数据组数。
每组数据由一行仅由数字组成的长度为N的非空字符串组成,表示矩阵有3行N 列,字符串的第i个数字字符表示矩阵中第2行第i个格子中的数字。
保证字符串长度N <= 10000,数据组数<= 100。
 

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

Sample Input
222000
 

Sample Output
61
 

Source
2016年中国大学生程序设计竞赛(合肥)-重现赛(感谢安徽大学)

分析:
  拿到这道题,首先想到的是深搜加剪枝,对于第一行和第二行的每个方格,有和没有地雷分别进行考虑,这种情况下稍微可以优化的就是,每找到一个八方格,就按照中间一行的数字进行判断是否符合扫雷规则,是就继续往下搜索,不是那么这种情况就不符合,此时结束这种情况的深搜,继续其他路径的深搜。
  但是和队友讨论之后,感觉这种方法并不会通过,于是就考虑另外的方法。
  我想到的另一个方法,就是将第一行和第三行的地雷合并,那么此时就只有两行,第一行就是原先中间的一行表示数字,第二行就是存放原先同列的第一行和第三行的地雷树,那么在第一列,我们确定了一其地雷数后,可以根据放地雷规则,依次找到后面每列的地雷数,具体如下图:
           
其中蓝色区域就是体现的地雷图的规则。根据规则,在n1下的地雷数确定后,可以依次往后推导出最后一行每个方格的地雷数,一直可以得到最后一列的地雷数,但是这里n[len-1]下的地雷数是利用n[len-2]根据规则推导出的,最后我们就根据规则,判断n[len-1]周围的八方格是否满足要求,也就是"n[len-2]下的地雷数+n[len-1]下的地雷数==n[len-1]",如果该成立,说明一开始我们令n1下的地雷数为x是满足要求的。
  这时求方案数,首先我们要知道,最后一行的每个方格的地雷数只能是0,1,2中的一个,因为其是由原先两个方格组合成,所以地雷数是原先每个方格数的两倍范围,即[0,1]*2=[0,2]。
  求方案数的时候,因为每个方格的地雷数都是各自独立的,如果为0,那么返回原先的情况,必须第一行和第二行的同列方格中每个方格地雷数都是0,就有一种情况;如果是1,那么同理就有两种情况,第一行有地雷,第三行没有或者反过来;如果是2,那么同理原先的对应两个方格必须都有地雷,只有一种情况。最后我们可以很容易使用类似独立事件的方法,将每个方格数中的地雷数根据刚才介绍的规则转换为方法数。
  最后,由于合并后的每个方格地雷数为0,1,2中的一种,我们将x=0,1,2的情况总数加起来即可。以下是源码:
#include<iostream>#include<string.h>#include<cstdio>using namespace std;#define Max 10000int zhuan[]={1,2,1};int arr[Max];int main(){   int N;   cin>>N;while(N--){  char str[10005];  scanf("%s",str);  int len=strlen(str);  int sum=0;  for(int x=0;x<=2;x++)  {       arr[0]=x;       arr[1]=str[0]-'0'-x;       if(arr[1]<0 || arr[1]>2)       {         continue;       }       bool isContinue=false;       for(int i=2;i<=len-1;i++)       {           arr[i]=str[i-1]-'0'-arr[i-1]-arr[i-2];           if(arr[i]<0 || arr[i]>2)           {              isContinue=true;              break;           }       }       if(isContinue)       {continue;}       int last=str[len-1]-'0';       if(arr[len-2]+arr[len-1]==last)       {            int cheng=1;            for(int j=0;j<=len-1;j++)            {                cheng*=zhuan[arr[j]];                cheng%=100000007;            }            sum+=cheng;            sum%=100000007;       }  }  printf("%d\n",sum);  }  return 0;}
最后需要提醒的是,这里输入输出,最好使用C语言的printf和scanf,并且输入数据利用字符数组保存,如果直接使用cin,cout和字符串类型接收输入数据,那么就会超时.(亲测提醒).



PS:好久没写博客了,比完蓝桥杯,也放松了。好消息是,哥哥要去北京了,哈哈。最近在老师的指导下,准备和学院的大牛组队参加CCPC,这道题目就是今早在和同学模拟刷题时遇到的。CCPC,蓝桥杯决赛,加油吧~
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 大连船员体检眼力不合格怎么办 禁行如果通过了怎么办 钻戒的戒圈磨损怎么办 多肉的肉掉了怎么办 电脑自带鼠标动不了怎么办 笔记本电脑自带鼠标动不了怎么办 包包弹簧扣松了怎么办 耳钉氧化成黑色怎么办 想买点小股票玩玩要怎么办 玩具子弹打到眼睛怎么办 玩具汽车遥控器码乱了怎么办 索尼A7屏幕花了怎么办? 汽车冷冻器坏了怎么办 sim卡损坏怎么办 补卡 异或门一个输入怎么办 迷你世界加不了好友怎么办 电脑软件显示无效应用程序怎么办 美的滚筒洗衣机打不开门怎么办 手机存储卡坏了怎么办 回南天地板潮湿怎么办 lg滚筒洗衣机门打不开怎么办 西门子滚桶洗衣机门打不开怎么办 洗衣机离合器螺丝卸不动怎么办 门锁保险栓坏了怎么办 小车电瓶没电了怎么办 重装机兵战车底盘坏了怎么办 父亲沉迷安利十年该怎么办 脚的大脚骨痛怎么办 自考准考证号忘记了怎么办 有桌子老师不出马怎么办 电商遇到职业打假人怎么办 超市遇到职业打假人怎么办 阿里巴巴碰到职业打假人怎么办 商家遇到职业打假人怎么办 买过期食品不赔怎么办 淘宝卖假货遇到打假师怎么办 网店遇到职业打假人怎么办 职业打假师把我起诉法院怎么办 被职业打假举报了怎么办 车档杆拉不动显示不在p档怎么办 宜人贷还不起了怎么办