zoukankan      html  css  js  c++  java
  • hiho_1114_扫雷

    http://hihocoder.com/problemset/problem/1114

    这道题,扫雷,两行,给出第二行全部的地雷数目,让我们猜测第一行。

    思路:

         考虑扫雷第二行数字的意义,(已知)[2][i]=[1][i-1]+[1][i]+[1][i+1]

         第二行是从1开始的,我们将第一行第[0]列当作是0,没有地雷,如果[1]确定了,那么[2]也确定了,[3].... 完美解决~

                       [1][0]=0 ,  [1][1]= 0/1/确定,[1][2] = [2][1] - [1][0] - [1][1]

         1、所以是枚举的问题,[1] 有两种可能0/1,所以枚举很简单。但是,扫雷是那么随便填的吗?!/反正是一把心酸泪被炸过来的/ 所以在枚举过程中可能会遇到某个格子填的数字是-1,比如

    0 0 2
    0 2  
    0 1 -1
    1 0  

          2、正常情况下[i]=0/1,所以每填一个数字都要检查一下,如果不是0/1,则弄个标志处理,表示当前第一个填0/1这种情况是不可取的。

          3、瞧,上面的右下角都有一个空缺,难不成第二行最后一个没用的么,当然不是,我们还要检测[2][n]==[1][n-1]+[1][n]是否符合,因为在填[1][n]和[1][n-1]时是根据[2][n-1]和[2][n-1]填的,并没有考虑到[2][n],所以要检测。

    tips:由于第一行最左边和最右边可以假想为没有炸弹,所以可以加上[0][n+1],在写迷宫类型的,也可以参照这种方式,在周边加上一个围栏
    好处:有些判断的情况上方便,不怕溢出,如 for循环[i-1] 不会越界,或者[i-1]=0的会使用时不会非法访问内存。
    瞎扯:在数学几何上的辅助线,一座通往光明的桥梁!小说里想象它们是小精灵来帮助我们~喵~

    AC代码:

    #include <iostream>
    #include <vector>
    #include<cstdio>
    using namespace std;
    int know[100010],a[2][100010];
    int main()
    {
        int T,n;
        cin >> T;
        while(T--){
            cin >> n;
            for(int i=1;i<=n;++i) scanf("%d",&know[i]);
            for(int first=0;first<2;++first){   // first 表示第一格子填的值是first,为0/1
                a[first][0]=a[first][n+1]=0;    // 假象的第0个或者第n+1个格子
                a[first][1]=first;          // 填第1个格子
                for(int i=2;i<=n+1;++i){       // 填2-n个格子,注意要填n+1格子主要是为了检测第二行第n个数字
                    a[first][i]=know[i-1]-a[first][i-1]-a[first][i-2]; // 填!
                    if(a[first][i]!=0&&a[first][i]!=1) {          // 检查
                        a[first][n+1]=1;
                        break;
                    }
                }
                if(a[first][n+1]!=0) // 如果这种情况不可取,那么把全部格子填成不是0/1的数字表示不可达的情况
                    for(int i=1;i<=n;++i) a[first][i]=-1;
            }
    
            int bomb=0,nobomb=0;
            for(int i=1;i<=n;++i){
                if(a[0][i]!=0&&a[1][i]!=0) bomb++;
                if(a[0][i]!=1&&a[1][i]!=1) nobomb++;
            }
    
    /*        for(int i=1;i<=n;++i)
                cout << a[0][i] <<" " ;
            cout << endl;
            for(int i=1;i<=n;++i)
                cout << a[1][i] <<" " ;
            cout << endl;
    */
    
            cout << bomb ;
            for(int i=1;i<=n;++i)
                if(a[0][i]!=0&&a[1][i]!=0) cout << " " << i ; // 如果a[0][]或a[1][]是错的,那么只会考虑到另一种情况,!=0是不会影响的。。。
            cout << endl;
    
            cout << nobomb;
            for(int i=1;i<=n;++i)
                if(a[0][i]!=1&&a[1][i]!=1) cout << " " << i ;
            cout << endl;
        }
        return 0;
    }
  • 相关阅读:
    上古神器之Vim编辑器
    Git
    Git
    php之IP
    PHP常见错误汇总
    Redis教程(Windows)
    如何使用RSS
    (转)Spring Boot干货系列:(三)启动原理解析
    (转)Maven创建webapp项目无法修改web版本的问题
    (转)图文详解MyEclipse中新建Maven webapp项目的步骤
  • 原文地址:https://www.cnblogs.com/tinyork/p/4266661.html
Copyright © 2011-2022 走看看