2018 蓝桥杯省赛 B 组模拟赛(一)

简介: 2018 蓝桥杯省赛 B 组模拟赛(一)

D题:最长上升子序列

给你一个序列,请你在其中求出一段最长严格上升的部分,它不一定要连续。

  #include<iostream>
    #include<cstring>
    using namespace std;
    int f[10000], b[10000];
    int lis(int n) {
        memset(f, 0, sizeof f);
        int res = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < i; ++j) {
                if (b[j] < b[i]) {
                    /*在这里填写必要的代码*/
                    if(f[j] + 1 > f[i])
                    {
                        f[i] = f[j] + 1;
                        res = max(res, f[i]);
                    }
                }
            }
            res = max(res, f[i]);
        }
        return res+1;
    }
    int main() {
        int n;
        scanf("%d", &n);
        for (int i = 0; i < n; ++i) {
            scanf("%d", b + i);
        }
        printf("%d\n", lis(n));
        return 0;
    }

E题:全排列

我们要找的是全排列中,排列结果互不相同的个数。比如:aab 的全排列就只有三种,那就是aab,baa,aba。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e3;
char str[N], buf[N];//buffer
int vis[N], total, len;
void arrange(int num) 
{
    if (num == len)
   {
        printf("%s\n", buf);
        total++;
        return;
    }
  for (int i = 0; i < len; ++i)
   {
        if (!vis[i])
      {
            int j;
            for (j = i + 1; j < len; ++j)
      {
                if (str[i] == str[j] && vis[j]在这里填写必要的代码) 
        {
                    break;
                }
            }
            if (j == len) 
        {
                vis[i] = 1;
                buf[num] = str[i];
                arrange(num + 1);
                vis[i] = 0;
            }
        }
    }
}
int main() {
    while (~scanf("%s",str))
 {
        len = strlen(str);
        sort(str, str + len);
        total = 0;
        buf[len] = '\0';
        arrange(0);
        printf("Total %d\n", total);
    }
    return 0;
}

{思路:填空的地方的意思是,如果i的后面有和s[i] 相等且访问过的字符,则不可以(break),一旦break,j 就不能等于len,就不能继续递归。那么怎么理解这个呢?}


先想一下简化的问题吧,假如输入的字符串不重复,例如abcd,那么就是简单的

dfs了,一个for循环加一个vis判断,如果判断可以,继续递归。当有重复的字符时候就比较麻烦了,比如aab,单纯的用递归会输出重复的。那么怎么加上限定条件呢。


这里,我们让重复的这些字符只顺序输出一遍,这样就不会重复


这是什么意思呢,比如说aabc,我们只允许第一个a访问后再访问第二个a,不允许访问第二个,再第一个。再如,abacda,那三个a只能按顺序访问。

原理是什么呢,用了点高中学的排列组合的知识,先排重复的,例如我们搞abacda这例子, 先排三个a, 就是 aaa,那么剩下的就相当于直接插入到aaa中,那么如果我们aaa如果按多种顺序排,就会产生多种结果,所以只能按顺序访问。

那么又如何用算法实现呢,直接加个if判断就行了,判断i之后的有没有访问过的且相等的。例如,aabc这个例子,我们第一轮选完之后,到了第二个a,然后进入递归,for循环又从0开始,到了第一个a,然后从这个之后去判断有没有访问过的a,结果判断有,违反了顺序,所以结束。

这个题目的关键也就是排除重复的


F题:数独

标准数独是由一个给与了提示数字的 9×9 网格组成,我们只需将其空格填上数字,使得每一行,每一列以及每一个 3×3 宫都没有重复的数字出现。


31.png

提醒:两个数字之间要有一个空格,其他地方不要输出多余的符号。

#include<iostream>
using namespace std;
int mp[90][90];
int hs(int x , int y , int i){ //判断行和列中有没有重复出现的数字 
    for(int j = 0; j < 9; j++){
        if(mp[x][j] == i && y != j)//行 
          return 0; 
        if(mp[j][y] == i && j != x)//列 
          return 0; 
    }
    return 1; 
}
int jiu(int x, int y, int n){//判断九个3X3的矩阵中有没有重复的数字 
    int xx = x / 3;//判断3X3矩阵左上方元素的位置 
    int yy = y / 3;
    for(int i = xx * 3; i < xx * 3 + 3; i++)
      for(int j = yy * 3; j < yy * 3 + 3; j++){
        if(mp[i][j] == n)
          if(i == x && j == y) continue;
          else return 0;
      }
    return 1;   
}
bool dfs(int cen){
    if(cen >= 81) return 1;//搜索完毕 
    int x = cen / 9;//判断当前位置的行坐标 
    int y = cen % 9;//列坐标 
    if(!mp[x][y]){//搜索当前位置的元素 
        for(int i = 1; i < 10; i++){ 
            mp[x][y] = i;//填数 
            if(jiu(x,y,i) && hs(x,y,i))//如果行列不冲突 
              if(dfs(cen + 1))//搜索下一个,下一个也不冲突,返回true,表示填数完成 
               return true;
            mp[x][y] = 0;//回溯 
        }
    }
    else return dfs(cen +1);//如果已经填入数字,搜索下一个,这里的返回很有灵性。
    return false; 
}
int main(){
    for(int i = 0; i < 9; i++){//输入字符,转换数字矩阵 
        for(int j = 0; j < 9; j++){
         char a; 
         cin >> a;
         if(a <= '9' && a >= '1')
           mp[i][j] = a - '0';
         else mp[i][j] = 0; 
        }
    }
    cout << endl;
    dfs(0);//从第一个开始搜索 
      for(int i = 0; i < 9; i++){//打印 
        for(int j = 0; j < 9; j++)
          cout << mp[i][j] << " ";
        cout << endl; 
      }
    return 0;
}

解题思路:DFS深度填数检测+回溯法

 1,先把有数字的地方设置标记位为true1
 2,循环遍历数组中没有标记位true1的地方,也就是需要填数的地方
       如果当前为0,即a[i][j]==0,判断当前所在的九宫格,然后从数字1-9依次检测是否在行、列、宫中唯一
                              满足唯一的话,则吧数字赋值给a[i][j]=l+1;然后继续深度遍历为true1的话就返回true1,否则回溯a[i][j]==0等
                              不满足满足唯一则判断下一个数字,直到1-9都判断不满足则返回false0,会回溯到上一层
   如果当前没有0,说明都已经填满且符合唯一条件,则返回true1;结束


相关文章
|
开发工具 git 编译器
Git 提交的正确姿势:Commit message 编写指南
Git 每次提交代码,都要写 Commit message(提交说明),否则就不允许提交。 $ git commit -m "hello world" 上面代码的-m参数,就是用来指定 commit mesage 的。
7498 0
|
7月前
|
运维 自然语言处理 算法
云栖实录 | 大模型在大数据智能运维的应用实践
云栖实录 | 大模型在大数据智能运维的应用实践
777 3
|
关系型数据库 Shell C#
PostgreSQL修改最大连接数
在使用PostgreSQL时,可能遇到“too many clients already”错误,这是由于默认最大连接数(100)不足。要增加此数值,需修改`postgresql.conf`中的`max_connections`参数
948 5
|
数据采集 测试技术 API
python爬虫之app爬取-微信朋友圈
搭建appium环境,appium基本使用,API操作等等
515 0
|
JavaScript 安全 前端开发
介绍DOM Based XSS
【8月更文挑战第25天】介绍DOM Based XSS
283 1
|
存储 人工智能 数据可视化
阿里云服务器的十二种典型应用场景
阿里云还提供了数据可视化服务DataV,帮助用户通过图形化的界面轻松搭建专业水准的可视化应用。用户可以利用DataV进行数据监控、调度和会展演示等工作,提高数据分析和决策的效率。
|
安全 关系型数据库 MySQL
基于SpringBoot+Vue+Mysql+Java 毕业生信息招聘平台系统(附源码)上
基于SpringBoot+Vue+Mysql+Java 毕业生信息招聘平台系统(附源码)
|
机器学习/深度学习 计算机视觉
【论文笔记】图像修复MPRNet:Multi-Stage Progressive Image Restoration 含代码解析1
【论文笔记】图像修复MPRNet:Multi-Stage Progressive Image Restoration 含代码解析
382 1
|
存储 算法 编译器
【C++ 函数 基础教程 第四篇】深入C++函数返回值:理解并优化其性能
【C++ 函数 基础教程 第四篇】深入C++函数返回值:理解并优化其性能
882 1
|
SQL 分布式计算 Hadoop
Hadoop学习笔记(HDP)-Part.15 安装HIVE
本文详细介绍Hive在Ambari集群中的安装与配置,涵盖MetaStore设置、高可用部署、Ranger权限管理及Beeline连接使用,助力构建安全高效的Hadoop数据仓库环境。
431 0