题目
简化版扫雷,只有一行。
给出一行的周围3格中是雷的数量。
判断哪些一定是雷,一定不是雷。
思路
因为给出的信息是环环相扣的,不用一个一个去试。
只需要试第一格是否为雷就可以通过数据算出后面是否为雷。
所以只用试两次,
第一次把一格设为雷,算出后面的情况;第二次把第一格设为不是雷,算出后面的情况。
若两次都算出来了,则将两次的情况对比,没有变化的部分就是答案。
若只有一次满足条件,则那一次直接就是答案。
代码
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=100000+2;
int N,M,a[MAXN],ans[2][MAXN],count[]={0,0},stat1[MAXN],stat2[MAXN];
int t1,t2;
bool run(int flag,int *s)
{
s[0]=0;
s[1]=flag;
for(int i=1;i<N;i++)
{
s[i+1]=a[i]-s[i]-s[i-1];
if(s[i+1]!=0 && s[i+1]!=1) return false;
}
if(a[N]==s[N-1]+s[N]) return true;
return false;
}
int main()
{
scanf("%d",&M);
a[0]=0;
while(M--)
{
t1=t2=count[0]=count[1]=0;
scanf("%d",&N);
for(int i=1;i<=N;i++) scanf("%d",&a[i]);
if(run(0,stat1)) t1=1;
if(run(1,stat2)) t2=1;
if(t1)
{
if(t2)
{
for(int i=1;i<=N;i++)
if(stat1[i]==stat2[i]) ans[stat1[i]][count[stat1[i]]++]=i;
}
else
{
for(int i=1;i<=N;i++)
ans[stat1[i]][count[stat1[i]]++]=i;
}
}
else if(t2)
{
for(int i=1;i<=N;i++)
ans[stat2[i]][count[stat2[i]]++]=i;
}
printf("%d",count[1]);
if(count[1])
{
for(int i=0;i<count[1];i++) printf(" %d",ans[1][i]);
}
printf("\n");
printf("%d",count[0]);
if(count[0])
{
for(int i=0;i<count[0];i++) printf(" %d",ans[0][i]);
}
printf("\n");
}
return 0;
}