2016年第七届C/C++ B组蓝桥杯省赛真题(下)

简介: 2016年第七届C/C++ B组蓝桥杯省赛真题

第七题:剪邮票

题目描述


017e81c286db657becf5cd3215f5a9a1.jpg


如【图1.jpg】, 有12张连在一起的12生肖的邮票。现在你要从中剪下5张来,要求必须是连着的。

(仅仅连接一个角不算相连)

比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。




请你计算,一共有多少种不同的剪取方法。


请填写表示方案数目的整数。

注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。


题目分析


直接搜索感觉很难实现,还要考虑去重和回溯的问题. 我们采用的方式是 全排列+深搜


可以创建一个数组,存放5个1,7个0,然后我们对其进行全排列(next_permutation()),判断该情况是否成立


如何判断:将一维数组转变成二维数组,然后进行深搜,最后统计连通块的个数.


如果只有一个连通块,说明该情况成立,否则循环判断下一个排列数.


题目代码

#include<bits/stdc++.h>
using namespace std;
int stamp[12] = { 0,0,0,0,0,0,0,1,1,1,1,1 }, map1[4][5];//一共12张邮票,需要剪下来五张
int NEXT[4][2] = {
  -1,0,//上
  1,0,//下
  0,-1,//左
  0,1//右
};
int ans = 0;//方案数
int book[4][5];//标记是否访问过
void dfs(int x, int y) {
  //结束条件
  if (map1[x][y] == 0) {
    return;//结束
  }
  for (int i = 0; i < 4; i++) {
    int tx = x + NEXT[i][0];
    int ty = y + NEXT[i][1];
    if (tx < 1 || tx>3 || ty < 1 || ty>4) { //判断是否越界
      continue;
    }
    if (!book[tx][ty]) {
      book[tx][ty] = 1;//进行标记
      dfs(tx, ty);//继续深搜
    }
  }
}
bool check() {
  //数据的初始化
  memset(book, 0, sizeof(book));
  int cnt = 0;//邮票连通块的个数
  int w = 0;
  //将一维数组转成二维
  for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 4; j++) {
      map1[i][j] = stamp[w++];
    }
  }
  for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 4; j++) {
      if (map1[i][j] == 1 && !book[i][j]) {
        book[i][j] = 1;//这里一定要注意,先标记后深搜,不然会陷入死循环呢.
        dfs(i, j);//进行深搜
//        book[i][j] = 1;
        cnt++;
      }
    }
  }
  return cnt == 1;//如果只有一个连通块则返回true,否则返回false
}
int main() {
  do {
    if (check()) {
      ans++;
    }
  } while (next_permutation(stamp, stamp + 12));
  cout << ans << endl;
  return 0;
}

参考答案

116

第八题:四平方和

题目描述

四平方和定理,又称为拉格朗日定理:每个正整数都可以表示为至多4个正整数的平方和。如果把0包括进去,就正好可以表示为4个数的平方和。比如:

5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2 (^符号表示乘方的意思)

对于一个给定的正整数,可能存在多种平方和的表示法。

要求你对4个数排序:0 <= a <= b <= c <= d

并对所有的可能表示法按 a,b,c,d 为联合主键升序排列,最后输出第一个表示法

程序输入为一个正整数N (N<5000000), 要求输出4个非负整数,按从小到大排序,中间用空格分开

例如

5
0 0 1 2

再例如

12
0 2 2 2

再例如

773535
1 1 267 838

资源约定:

峰值内存消耗 < 256M

CPU消耗 < 3000ms

题目分析

暴力枚举+剪枝

数据量是 5*10^6,直接暴力枚举必定爆!可以采用以下剪枝


根据四平方和定理, 数据a,b,c,d范围都是 <= sqrt(n)

写四层for必定超时,最后一层可以用 n - (a*a + b*b + c*c) 表示,这样就少了一个循环.

第二、三层开始进行剪枝约束。只要值超过 n,则直接break.

最后一个循环中判断a,b,c确定后的d是不是整数.需要用到强制转换.


注意:


double类型的数据强制转换没有误差,但运行运算时可能出现误差.


sqrt()的返回值是double类型


计算机1s大约运行10^8次,可以根据这个简单判断程序是否超时.


题目代码

#include<bits/stdc++.h> 
using namespace std;
int main(){
  int n;//最多三个循环+剪枝操作
  cin>>n;
  int q =  (int)sqrt(n);//sqrt的返回值是double类型 
  for(int a = 0;a<=q;a++){
    for(int b = 0; b<=q;b++){
      //开始第一轮剪枝
      if(a*a+b*b>n) {//直接结束循环,因为后面的数更大 
        break;
      }
      for(int c = 0; c <=q;c++) {
        //开始第二轮剪枝 
        if(a*a+b*b+c*c > n){
          break;
        }
        double d = sqrt(n - (a*a+b*b+c*c)) ;//判断d是否可以分解成两个整数的平方 
        if(d==(int)d){
          cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
          return 0;
        }
      }
    }
  }
  return 0;
}

第九题:交换瓶子

题目描述

有N个瓶子,编号 1 ~ N,放在架子上。


比如有5个瓶子:2 1 3 5 4


要求每次拿起2个瓶子,交换它们的位置。经过若干次后,使得瓶子的序号为:1 2 3 4 5


对于这么简单的情况,显然,至少需要交换2次就可以复位。


如果瓶子更多呢?你可以通过编程来解决。


输入格式为两行:

第一行: 一个正整数N(N<10000), 表示瓶子的数目

第二行:N个正整数,用空格分开,表示瓶子目前的排列情况。


输出数据为一行一个正整数,表示至少交换多少次,才能完成排序。

输入样例

样例1

5
3 1 2 5 4
3

样例2

5
5 4 3 2 1
2

资源约定:

峰值内存消耗 < 256M

CPU消耗 < 1000ms


题目分析

使用一个标记数组,在输入元素时,记录元素的位置.之后遍历排序时,如果元素和该位置A应该放置的元素B不同时,根据标记数组找到元素B位置,和当前元素A进行交换. 时间复杂度为 O ( n ) O(n)O(n).


题目代码

#include<bits/stdc++.h> 
using namespace std;
const int M = 10000+5;
int arr[M],book[M];//book:标记数组,记录元素的所在.  arr:原始数组 
int main(){
  int n,ans;
  ans = 0;
  cin>>n;
  for(int i = 1; i <= n;i++){
    cin>>arr[i];
    book[arr[i]] = i;
  }
  for(int i = 1; i<= n;i++) {
    if(arr[i]!=i){
      swap(arr[i],arr[book[i]]);
      ans++; 
    }
  }
  cout<<ans<<endl;
  return 0;
}

第十题:最大比例

题目描述

X星球的某个大奖赛设了M级奖励。每个级别的奖金是一个正整数。并且,相邻的两个级别间的比例是个固定值。


也就是说:所有级别的奖金数构成了一个等比数列。比如:16,24,36,54 其等比值为:3/2


现在,我们随机调查了一些获奖者的奖金数。请你据此推算可能的最大的等比值。


输入格式:

第一行为数字N,表示接下的一行包含N个正整数

第二行N个正整数Xi(Xi<1 000 000 000 000),用空格分开。每个整数表示调查到的某人的奖金数额


要求输出:

一个形如A/B的分数,要求A、B互质。表示可能的最大比例系数


测试数据保证了输入格式正确,并且最大比例是存在的。

输入样例

样例1

3
1250 200 32
25/4

样例2

4
3125 32 32 200
5/2

样例3

3
549755813888 524288 2
4/1

资源约定:

峰值内存消耗 < 256M

CPU消耗 < 3000ms

题目分析

题目代码

待续...

备注:由于蓝桥杯不再考察补全代码题型,所以未整理总结其思路

如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发。

创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客

相关文章
|
1月前
|
算法 测试技术 C++
【动态规划算法】蓝桥杯填充问题(C/C++)
【动态规划算法】蓝桥杯填充问题(C/C++)
|
1月前
|
人工智能 算法 BI
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
|
1月前
|
人工智能 C++
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
第十四届蓝桥杯省赛大学B组(C/C++)整数删除
|
1月前
|
机器学习/深度学习 算法 关系型数据库
第十五届蓝桥杯C++B组省赛
第十五届蓝桥杯C++B组省赛
79 14
|
1月前
|
算法 C++
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
37 5
|
6月前
|
算法 测试技术 C++
小唐开始刷蓝桥(八)2013年第四届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(八)2013年第四届C/C++ B组蓝桥杯省赛真题
|
6月前
|
算法 C++ 数据格式
小唐开始刷蓝桥(七)2014年第五届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(七)2014年第五届C/C++ B组蓝桥杯省赛真题
|
6月前
|
算法 C++
小唐开始刷蓝桥(五)2016年第七届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(五)2016年第七届C/C++ B组蓝桥杯省赛真题
|
6月前
|
算法 C++
小唐开始刷蓝桥(六)2015年第六届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(六)2015年第六届C/C++ B组蓝桥杯省赛真题
|
6月前
|
数据安全/隐私保护 C++
小唐开始刷蓝桥(九)2012年第三届C/C++ B组蓝桥杯省赛真题
小唐开始刷蓝桥(九)2012年第三届C/C++ B组蓝桥杯省赛真题