洛谷 P2327 [SCOI2005]扫雷

P2327 [SCOI2005]扫雷

https://www.luogu.org/problem/show?pid=2327

题目描述

输入输出格式

输入格式:

第一行为N,第二行有N个数,依次为第二列的格子中的数。(1<= N <= 10000)

输出格式:

一个数,即第一列中雷的摆放方案数。

输入输出样例

输入样例#1:

2
1  1

输出样例#1:

2

算法1:

枚举左边每个位置是否有雷,复杂度O(2^n*n)。

算法2:

我们发现,当前两个位置确定时,后面的位置也就可以推出来了。

于是我们可以只枚举前两位。

复杂度O(n)

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,num[10010],a[10010];
bool mine[10010],flag;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&num[i]);
    if(num[1]==3){printf("0");return 0;}
    if(num[1]==2){
        mine[1]=1;mine[2]=1;
        a[1]=2;
        for(int i=2;i<=n-1;i++){
            for(int j=i-1;j<=i+1;j++)a[i]+=mine[j];
            if(a[i]==num[i])mine[i+1]=0;
            else if(a[i]==num[i]-1)a[i]++,mine[i+1]=1;
            else {flag=1;break;}
        }
        if(flag==1){printf("0");return 0;}
        a[n]+=mine[n-1];a[n]+=mine[n];
        if(a[n]==num[n]){printf("1");return 0;}
        else{printf("0");return 0;}
    }
    if(num[1]==1){
        int ans=0;
        mine[1]=1;mine[2]=0;
        a[1]=1;
        for(int i=2;i<=n-1;i++){
            for(int j=i-1;j<=i+1;j++)a[i]+=mine[j];
            if(a[i]==num[i])mine[i+1]=0;
            else if(a[i]==num[i]-1)a[i]++,mine[i+1]=1;
            else {flag=1;break;}
        }
        if(flag!=1){a[n]+=mine[n-1];a[n]+=mine[n];if(a[n]==num[n])ans++;}

        memset(mine,0,sizeof(mine));
        memset(a,0,sizeof(a));
        mine[1]=0;mine[2]=1;
        a[1]=1;
        for(int i=2;i<=n-1;i++){
            for(int j=i-1;j<=i+1;j++)a[i]+=mine[j];
            if(a[i]==num[i])mine[i+1]=0;
            else if(a[i]==num[i]-1)a[i]++,mine[i+1]=1;
            else {flag=1;break;}
        }
        if(flag!=1){a[n]+=mine[n-1];a[n]+=mine[n];if(a[n]==num[n])ans++;}
        printf("%d",ans);return 0;
    }
    if(num[1]==0){
        mine[1]=0;mine[2]=0;
        a[1]=0;
        for(int i=2;i<=n-1;i++){
            for(int j=i-1;j<=i+1;j++)a[i]+=mine[j];
            if(a[i]==num[i])mine[i+1]=0;
            else if(a[i]==num[i]-1)a[i]++,mine[i+1]=1;
            else {flag=1;break;}
        }
        if(flag==1){printf("0");return 0;}
        a[n]+=mine[n-1];a[n]+=mine[n];
        if(a[n]==num[n]){printf("1");return 0;}
        else{printf("0");return 0;}
    }
}
时间: 2024-10-24 14:12:26

洛谷 P2327 [SCOI2005]扫雷的相关文章

洛谷P2327 [SCOI2005]扫雷 枚举 搜索

洛谷P2327 [SCOI2005]扫雷 枚举 搜索 对搜索的 一些优化 其实我们只要枚举第一行是否有地雷,根据第1行探测出的地雷数,就可以推出第二行是否有地雷 然后在根据第二行探测地雷数推出第三行的情况,这样以此类推,一直推到第 n-1 的探测结果,然后 推出第 n 行是否有地雷如果在推的过程中 使得当前的探测地雷数为 负数 ,说明这个方法是萎的, 或者这一行推完了之后,还是有雷,那也退出,最后还要判断一下第 n 行是否有地雷 1 #include <cstdio> 2 #include &

P2327 [SCOI2005]扫雷 [2017年5月计划 清北学堂51精英班Day1]

P2327 [SCOI2005]扫雷 题目描述 输入输出格式 输入格式: 第一行为N,第二行有N个数,依次为第二列的格子中的数.(1<= N <= 10000) 输出格式: 一个数,即第一列中雷的摆放方案数. 输入输出样例 输入样例#1: 2 1 1 输出样例#1: 2 其实还是扫雷玩的少..知道思路之后很快 只需枚举前两个各自的情况,后面的各自便能够计算出来 注意几个细节(在代码里面) #include <iostream> #include <cstdio> #in

题解 P2327 [SCOI2005]扫雷

题解 P2327 [SCOI2005]扫雷 题目链接 普及组水题非常适合新手练搜索 看题解里各路神仙都用各种简单的方法,我来讲讲暴力搜索做法.... 对于我这样的萌新我觉得这样的做法更容易让你理解搜索 首先搜索要定义状态,我们定义dfs(x, p)是当第x位是p,就有了状态 然后我们讨论第x + 1位的情况只有两种情况,然后就有了转移 其次当x是n时,如果成立,则++ans,于是有了边界条件 最后你把这段代码复制粘贴得了100分,发现原来这有点像动态规划 #include <iostream>

洛谷 P2324 [SCOI2005]骑士精神

P2324 [SCOI2005]骑士精神 题目描述 输入输出格式 输入格式: 第一行有一个正整数T(T<=10),表示一共有N组数据.接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑士,*表示空位.两组数据之间没有空行. 输出格式: 对于每组数据都输出一行.如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1. 输入输出样例 输入样例#1: 2 10110 01*11 10111 01001 00000 01011 110*1 01110 01010 00100 输出样例

P2327 [SCOI2005]扫雷

题目描述 相信大家都玩过扫雷的游戏.那是在一个 n×mn\times mn×m 的矩阵里面有一些雷,要你根据一些信息找出雷来.万圣节到了,“余”人国流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子没有雷,那么它里面的数字表示和它8连通的格子里面雷的数目.现在棋盘是 n×2n\times 2n×2 的,第一列里面某些格子是雷,而第二列没有雷,如下图: 由于第一列的雷可能有多种方案满足第二列的数的限制,你的任务即根据第二列的信息确定第一列雷有多少种摆放方案. 输入输出格式 输入格式:

Luogu P2327 [SCOI2005]扫雷【递推/数学】By cellur925

题目传送门 推了好久啊.看来以后要多玩扫雷了qwq. 其实本题只有三种答案:0.1.2. 对于所有第一列,只要第一个数和第二个数确定后,其实整个数列就确定了,我们可以通过这个递推式得出 1 sec[i-1]=fir[i]+fir[i-2]+fir[i-1] 所以我们可以枚举每列的第1/2个数. 如果推到第n+1个数还存在,那么指定这种情况不成立. Code 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring&

洛谷P2331 [SCOI2005] 最大子矩阵[序列DP]

题目描述 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵不能相互重叠. 输入输出格式 输入格式: 第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767). 输出格式: 只有一行为k个子矩阵分值之和最大为多少. 输入输出样例 输入样例#1: 3 2 2 1 -3 2 3 -2 3 输出样例#1: 9 m分类讨论m=1,f[i][j]表示前i个选了j个矩

洛谷 P1896 [SCOI2005]互不侵犯King

题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入输出格式 输入格式: 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <= K <= N * N) 输出格式: 所得的方案数 输入输出样例 输入样例#1: 3 2 输出样例#1: 16 #include<cstdio> #include<cstring> #include<ios

洛谷 P2325 [SCOI2005]王室联邦

题目描述 "余"人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理. 他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条直接或间接的道路.为了防止管理太过分散,每个省至少要有B个城市,为了能有效的管理,每个省最多只有3B个城市. 每个省必须有一个省会,这个省会可以位于省内,也可以在该省外.但是该省的任意一个城市到达省会所经过的道路上的城市(除了最后一个城市,即该省省会)都必须属于该省. 一个城市