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;结束


相关文章
|
1月前
|
人工智能 C++
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
|
6月前
|
机器学习/深度学习 人工智能 测试技术
棋盘(来源:第十四届蓝桥杯省赛JavaA/C/研究生组 , 第十四届蓝桥杯省赛PythonC组)
棋盘(来源:第十四届蓝桥杯省赛JavaA/C/研究生组 , 第十四届蓝桥杯省赛PythonC组)
|
6月前
|
测试技术
消除游戏(第十三届蓝桥杯省赛C++C组 , 第十三届蓝桥杯省赛PythonA/B/研究生组)
消除游戏(第十三届蓝桥杯省赛C++C组 , 第十三届蓝桥杯省赛PythonA/B/研究生组)
消除游戏(第十三届蓝桥杯省赛C++C组 , 第十三届蓝桥杯省赛PythonA/B/研究生组)
|
6月前
|
测试技术
保险箱(第十四届蓝桥杯省赛PythonB组)
保险箱(第十四届蓝桥杯省赛PythonB组)
蓝桥青少年组——计算24 2020-11-25
蓝桥青少年组——计算24 2020-11-25
|
存储 人工智能 测试技术
第十二届蓝桥杯省赛第二场 C/C++ B组 编程题与详解
第十二届蓝桥杯省赛第二场 C/C++ B组 编程题与详解
158 0
|
人工智能 C++
第十届蓝桥杯省赛 C++ B/C组 - 等差数列
第十届蓝桥杯省赛 C++ B/C组 - 等差数列
110 0
|
C++
第八届蓝桥杯省赛 C++ A/B组 - 分巧克力
第八届蓝桥杯省赛 C++ A/B组 - 分巧克力
108 0
第十一届蓝桥杯省赛 - B组
第十一届蓝桥杯省赛 - B组
94 0
|
C++
第十二届蓝桥杯省赛第二场 C++ B组 - 小平方
第十二届蓝桥杯省赛第二场 C++ B组 - 小平方
64 0