挖地雷题解

穿越了茫茫沙漠后,黑暗军团的前方出现了地雷阵,该地雷阵类似于Windows操作系统自带的挖地雷游戏,但此处仅有一行地雷,如图8.5所示,表中第一行有*号的位置表示一颗地雷。而第二行每格中的数字表示与其相邻的三格中地雷的总数。

输入数据给定一行的格子数n(n≤10000)和第二行的各个数字,编程求第一行的地雷分布。

【输入格式】

输入文件为bomp.in,第一行为一个整数n,第二行为各个数字。

【输出格式】

输出文件为bomp.out,以01顺序输出地雷分布图,其中有地雷以1表示,否则以0表示。若无解,则输出“No answer”。

【输入样例】

8

2 2 2 2 3 2 2 1

【输出样例】

1 1 0 1 1 1 0 1

 

窝再提供一组hank数据:

4

1 2 2 1

好了正解开始:

证明:设第一个位置为1或0,即代表有无地雷,那么后面的都可以推出来,也就是唯一确定。

这个怎么证明?

很简单,对于一个数字,他表示当前位置左右共3个格子的雷总数,那么只要知道这个数,并知道三个位置中两个的情况,那么一定能推出剩下的那个;

对于开头和结尾,因为每个数字只能表示两个格子内的情况,那么我们只需知道一个格子内的情况,就可以推出两个格子的情况,进而推出三个格子的情况,所以关键在于枚举那一个格子。

一个格子只有0或1两种情况,枚举第一个后往后递推,遇到一个格子上有2个地雷或者-1个地雷的情况直接输出无解(因为样例不保证有解)。那么这O(2n)(O(n))的递推算法就成了QWQ。

#include<cstdio>
#include<cstring>
using namespace std;
int read()
{
    int ans=0;
    char ch=getchar(),last=' ';
    while(ch<'0'||ch>'9')
    {
        last=ch,ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        ans=(ans<<3)+(ans<<1)+ch-'0';
        ch=getchar();
    }
    return last=='-'?-ans:ans;
}
int n,dl[10001];
int ans[10001],ans2[10001];
bool flag1,flag0;
inline void print()
{
    for(int i=1;i<=n;i++)
    {
        printf("%d ",ans[i]);
    }
}
inline void print2()
{
    for(int i=1;i<=n;i++)
    {
        printf("%d ",ans2[i]);
    }
}
int main(){
    freopen("bomp.in","r",stdin);
    freopen("bomp.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)
    {
        dl[i]=read();
    }
    ans[1]=1;
    for(int i=1;i<=n;i++)
    {
        if(i==1){
            ans[2]=dl[1]-ans[1];
            if(ans[2]<0||ans[2]>1)flag1=1;
        }
        if(i==n){
            if(dl[i]-ans[i-1]-ans[i]!=0)flag1=1;
        }
        else{
            ans[i+1]=dl[i]-ans[i-1]-ans[i];
            if(ans[i+1]<0||ans[i+1]>1)flag1=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(i==1){
            ans2[2]=dl[1]-ans2[1];
            if(ans2[2]<0||ans2[2]>1)flag0=1;
        }
        if(i==n){
            if(dl[i]-ans2[i-1]-ans2[i]!=0)flag0=1;
        }
        else{
            ans2[i+1]=dl[i]-ans2[i-1]-ans2[i];
            if(ans2[i+1]<0||ans2[i+1]>1)flag0=1;
        }
    }
    if(flag1==1&&flag0==0)print2();
    else
    if(flag1==0&&flag0==1)print();
    else
    if(flag1==0&&flag0==0)print();
    else printf("No answer");
}

完结

posted @ 2019-07-09 20:52  李白莘莘学子  阅读(578)  评论(0编辑  收藏  举报