时间限制: 1 Sec 内存限制: 128 MB
提交: 187 解决: 32
题目描述
小Q空的时候挺喜欢玩玩电脑游戏的。自从编程技术提高后,他就想,要是自己也能开发出一款游戏来,那该多好啊!不过,小Q也不着急,先练好基本功再说。Windows中就有一款叫扫雷的小游戏,挺好玩的,不过想编出一个来,还真不容易。小Q就自己设想了一种简单的扫雷游戏:在n行2列的方格棋盘上,左列某些方格内埋有地雷,而右列每个方格中都有一个数字(0~3),第I格的数字表示:左列第I-1、I、I+1格(即:上、中、下三格)中埋雷的总数。如下所示:左图是初始状态,右图是扫雷完成状态(插小旗的方格内有雷)。
你的任务是:根据右列的数字分析出左列格子中的地雷(0表示无雷,1表示有雷),并且统计出左列格子中地雷的总数。
小Q想,如果这样的任务能完成了,相信编出更复杂的扫雷游戏也就为期不远了。
输入
第一行,一个整数N(2≤N≤40),第二行有N个数字(以一个空格相隔),表示右列格子中的数字。输入数据保证正确有解。
输出
第一行是N个0、1数字(没有空格相隔),表示左列每格中有无地雷。第二行一个整数,表示地雷总数。
样例输入
7
1 2 3 2 2 2 2
样例输出
0111011
5
这个题当时就差一点点就做出来了,只少了一句
if(a[0][1]==0)
mark=1;
我的做法也没有什么技巧,就是利用一个小规律。
只要我能确定出第一个格子有没有雷,题目其实就已经解决了。第一个格子无非两种情况,有雷or无雷,这样就可以先假设第一个格子有雷,这样根据a【0】【1】的值就可以确定第二个有没有雷,然后后面的就都出来了,在推出后面的时候如果出现矛盾,则假设是错的,转而让第一个格子没有雷,在进行一次推理就可以了。
昨天错在哪了呢,如果输入的a【0】【1】为0,在数据少于3个时 我先假设有雷的话会默认第一个有雷(由于数据较少不会进入循环,无法判断是否矛盾),这和a【0】【1】为0是互相矛盾的,但是我没有去判断这个矛盾,导致出错。所以加上上面那一句,判断一下就好了。(找了好久。。。。)
#include <stdio.h>
int main()
{
int n;
int a[40][2];
int mark=0;
int cnt;
int x=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i][1]);a[i][0]=0;
}
if(a[0][1]==0)
mark=1; //判断一下前两个格没有雷的情况,以免数据少时出错
else
{
a[0][0]=1; //假设第一格有雷
if(a[0][1]==2) //推第二格
a[1][0]=1;
else
a[1][0]=0;
}
for(int i=1;i<n-1;i++)
{
cnt=0;
for(int j=i-1;j<=i;j++)
if(a[j][0]==1)
cnt++;
if(a[i][1]-cnt==1)
a[i+1][0]=1; //推出后面
else if((cnt+1)<a[i][1]) //这里是矛盾判断,如果雷数+1还比总雷数小,那假设第一个有雷这种情况就不对了 ,做个标记,退出循环。
{
for(int k=0;k<n;k++) a[k][0]=0;
mark=1;break;
}
}
if(mark==1) //如果第一格有雷不成立
{
a[0][0]=0;
if(a[0][1]==1)
a[1][0]=1;
else
a[1][0]=0;
for(int i=1;i<n-1;i++)
{
cnt=0;
for(int j=i-1;j<=i;j++)
if(a[j][0]==1)
cnt++;
if(a[i][1]-cnt==1)
a[i+1][0]=1;
}
}
for(int i=0;i<n;i++)
{
printf("%d",a[i][0]);if(a[i][0]==1) x++;
}
printf("\n");
printf("%d",x);
return 0;
}