第十四届蓝桥杯省赛C++B组题解

考点

暴力枚举,搜索,数学,二分,前缀和,简单DP,优先队列,链表,LCA,树上差分

A 日期统计

暴力枚举:

#include<bits/stdc++.h>
using namespace std;
int b[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int a[50];
int h,m,s;
set<int>q;//用来排重
int main()
{  
    for(int i=1;i<=40;i++)//年份已固定,只用从后40位枚举
    {
        cin>>a[i];
    }
    for(int i=1;i<=40;i++)
        for(int j=i+1;j<=40;j++)
         for(int k=j+1;k<=40;k++)
             for(int p=k+1;p<=40;p++)
             {
                 h=a[i]*1000+a[j]*100+a[k]*10+a[p];
                 m=a[i]*10+a[j];
                 s=a[k]*10+a[p];
                 if(m>0&&m<=12&&s>0&&s<=b[m])
                     q.insert(h);
             }
    cout<<q.size()<<endl;
}

B 01串的熵

暴力枚举:

#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    int n = 23333333;
    for (int i = 1; i < n; ++i)
    {
        double a = i * 1.0 / n;  // 0出现的占比
        double b = (n - i) * 1.0 / n;  // 1出现的占比
        double res = 0;
        res -= a * log2(a) * i + b * log2(b) * (n - i);
        if (fabs(res - 11625907.5798) < 0.0001)
        {
            cout << i << endl;
            break;
        } 
    }
    return 0;
}

C 冶炼金属

解题思路:
最大值可以遍历比较得出,但是最小值要么使用数学公式,要么就是二分答案

公式法:

#include <iostream>
using namespace std;
typedef long long ll;
ll N,A[10010],B[10010],res[10010],res2[10010];
ll minres=1e9+7;
ll maxres2=-1;
int main()
{
  cin>>N;

  for(int i=0;i<N;i++){
      cin>>A[i]>>B[i];
      res[i]=A[i]/B[i];
      minres=min(minres,res[i]);
      res2[i]=A[i]/(B[i]+1);
      maxres2=max(maxres2,res2[i]);
  }
  
  cout<<maxres2+1<<" "<<minres;
  return 0;
}

二分答案:

#include<bits/stdc++.h>
using namespace std;
int a[200100],b[200100],n;
int find(int x){
	for(int i=1;i<=n;i++){
		if(a[i]/x>b[i]){
			return 1;
		}else if(a[i]/x<b[i]){
			return 0;
		}
	}
	return 0;
}
int main(){
	int minn=INT_MAX,maxx=INT_MAX;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i];
		maxx=min(maxx,a[i]/b[i]);
	}
	int l=0,r=1e9,mid=0;
	while(l<=r){
		mid=(l+r)/2;
		if(find(mid)){
			l=mid+1;
		}else{
			r=mid-1;
		}
	}
	cout<<l<<" "<<maxx<<endl;
	return 0;
}

D 飞机降落

题目大意:
给你n架飞机的到达,降落花费和可等待时间,让你求是否能全部安全降落

解题思路:
因为最大数据为10,直接上dfs,遍历所有情况,是否有可以降落的情况,注意一下回溯和边界处理就行。(多实例,记得将标记数组初始化)

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl "\n";
int t[20],d[20],l[20],vis[20];
int n,flag; 
void dfs(int sum,int ans){
	if(ans>=n){
		flag=1;
		return ;
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]&&(sum<=t[i]||sum<=t[i]+d[i])){
			if(sum<=t[i]){
				vis[i]=1;
				dfs(t[i]+l[i],ans+1);
			}else if(sum<=t[i]+d[i]){
				vis[i]=1;
				dfs(sum+l[i],ans+1);
			}else{
				continue;
			}
			vis[i]=0;
		}
	}
} 
void solve(){
	memset(vis,0,sizeof(vis));
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>t[i]>>d[i]>>l[i];
	}
	flag=0;
	dfs(0,0);
	if(flag){
		cout<<"YES"<<endl;
	}else{
		cout<<"NO"<<endl;
	}
	return ;
}
signed main()
{
	IOS
	int t=1;
	cin>>t;
	while(t--)
	solve();
    return 0;
}

E 接龙数列

题目大意:

给你n个数,问你删除几个可以将剩下的组成接龙数列。

解题思路:
因为接龙数列只需要判断首个数字和末尾数字,而且只能有 0 − 9 0-9 09十种可能,所以,只需要开一个dp数组,将每个数的首个数字和末尾数字进行存储,并更新以末尾数字结尾的数组,即是否小于当前以首个数字结尾的接龙数列的长度+1的长度,小于则更新,最后输出最长的一个接龙数列的长度即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl "\n";
int dp[20];
void solve(){
	int n,maxx=0,a,b;
	string x;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x;
		a=x[0]-'0';
		b=x[x.size()-1]-'0';
		dp[b]=max(dp[b],dp[a]+1);
		maxx=max(dp[b],maxx);
	}
	cout<<n-maxx<<endl;
	return ;
}
signed main()
{
	IOS
	int t=1;
	//cin>>t;
	while(t--)
	solve();
    return 0;
}

F 岛屿个数

题目大意:
给你一个n*m的矩阵,由海0和陆地1组成,一个1围成的还就是一个岛屿,但是岛屿里面的岛屿属于子岛屿,不属于岛屿的范畴,让你求一共由多少个岛屿。

解题思路:
因为有环中环的情况,而且只需要判断最外环的情况,所以从最外围的海水开始遍历,接触到最外围海水的一定是岛屿,然后就先dfs一遍把最外围海水标记了,再从外围海水向陆地dfs一遍,每次遍历岛屿数量都加一,最后得出结果。

#include <stdio.h>
#include <stdlib.h>

int M, N, d[52][52];

void dfs_sea(int i, int j)
{
    if ((i >= 0 && i <= M + 1) && (j >= 0 && j <= N + 1))
    {
        if (d[i][j] == 0)
        {
            d[i][j] = 2;//标记出外海
            //八个方向 
            dfs_sea(i, j + 1);
            dfs_sea(i, j - 1);
            dfs_sea(i + 1, j);
            dfs_sea(i + 1, j + 1);
            dfs_sea(i + 1, j - 1);
            dfs_sea(i - 1, j);
            dfs_sea(i - 1, j + 1);
            dfs_sea(i - 1, j - 1);
        }
    }
}

void dfs_island(int i, int j)
{
    if ((i >= 0 && i <= M + 1) && (j >= 0 && j <= N + 1))
    {
        if (d[i][j] == 1)
        {
            d[i][j] = 3;//搜索过的岛屿不再搜索 
            dfs_island(i + 1, j);//右 
            dfs_island(i - 1, j);//左 
            dfs_island(i, j + 1);//上 
            dfs_island(i, j - 1);//下 
        }
    }
}

int main(int argc, char *argv[])
{
    // 请在此输入您的代码
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d %d", &M, &N);
        //填充海水
        for (int i = 0; i < N + 2; i++)
        {
            d[0][i] = 0;
            d[M + 1][i] = 0;
        }
        for (int i = 1; i < M + 1; i++)
        {
            d[i][0] = 0;
            d[i][N + 1] = 0;
        }
        //输入图 
        for (int i = 1; i < M + 1; i++)
        {
            for (int j = 1; j < N + 1; j++)
            {
                scanf("%1d", &d[i][j]);
            }
        }

        dfs_sea(0, 0); //找出所有外海 

        int count;//计算岛屿数量 
        count = 0;
        for (int i = 0; i < M + 2; i++)
        {
            for (int j = 0; j < N + 2; j++)
            {
                if (d[i][j] == 1 && d[i - 1][j] == 2)//只能从外海搜索岛屿,所以岛屿前一定是外海“2”
                {
                    dfs_island(i, j);//搜索岛屿 
                    count++;
                }
            }
        }
        printf("%d\n", count);
    //以下代码可以打印出处理后的图
        /*for (int i = 0; i < M + 2; i++)
        {
            for (int j = 0; j < N + 2; j++)
            {
                printf("%1d", d[i][j]);
                if (j == N + 1)
                printf("\n");
            }
        }*/
    }
    return 0;
}

G 子串简写

题目大意:给定一个字符串和一个长度K,再给出两个字符a和b,求字符串有多少个长度大于等于K且是以a为首字母,b为尾字母的子串。

解题思路:
因为只需要判断首尾,所以可以直接从字符串的尾部向前遍历并用前缀和来记录b字符的个数,最后字符串从前往后遍历,每遇到一个a字符,就判断在其k-1的长度后,有多少个b字符,将其数量累加,最后输出即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long 
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl "\n";
int sum[1000100];
void solve(){
	int n,num=0;
	string x;
	char aa,bb;
	cin>>n;
	cin>>x;
	cin>>aa>>bb;
	for(int i=x.size()-1;i>=0;i--){
		if(x[i]==bb){
			sum[i]+=sum[i+1]+1;
		}else{
			sum[i]+=sum[i+1];
		}
	}
	for(int i=0;i<x.size();i++){
		if(x[i]==aa){
			num+=sum[i+n-1];
		}
	}
	cout<<num<<endl;
	return ;
}
signed main()
{
	IOS
	int t=1;
	//cin>>t;
	while(t--)
	solve();
    return 0;
}

H 整数删除

题目大意:给你n个数,和k次操作,每次操作将当前剩余数中最小数的左右两个数加上当前最小数的值(多个最小数从前往后进行操作,左边或者右边没有数则不操作),并将这个最小数剔除,问你k次操作后的序列是什么。

解题思路:
因为需要动态维护最小值,所以使用优先队列,但是因为每次进行操作后,最小值可能会发生变化,所以需要加上双向链表进行优化。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

const int N = 5e5 + 10;
ll v[N], l[N], r[N];

void del(int x) {
    r[l[x]] = r[x], l[r[x]] = l[x];
    v[l[x]] += v[x], v[r[x]] += v[x];
}

int main () {
    int n, k; cin >> n >> k;
    r[0] = 1, l[n + 1] = n;
    priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> h;
    for (int i = 1; i <= n; i ++)
        cin >> v[i], l[i] = i - 1, r[i] = i + 1, h.push({v[i], i});
    while (k --) {
        auto p = h.top(); h.pop();
        if (p.first != v[p.second]) h.push({v[p.second], p.second}), k ++;
        else del(p.second);
    }
    int head = r[0];
    while (head != n + 1) {
        cout << v[head]<< " ";
        head = r[head];
    }
    return 0;
}

最后两题考到了LCA算法,有点属于盲区了算是,回去恶补一下,两周内题解补上!!!

相关推荐

  1. C++B题解

    2024-03-19 11:54:03       42 阅读
  2. 2023C/C++大学A题解

    2024-03-19 11:54:03       34 阅读
  3. C++ C《全题目+题解

    2024-03-19 11:54:03       34 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-19 11:54:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-19 11:54:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-19 11:54:03       82 阅读
  4. Python语言-面向对象

    2024-03-19 11:54:03       91 阅读

热门阅读

  1. 数据仓库作业二:第2章 数据仓库原理

    2024-03-19 11:54:03       31 阅读
  2. 云项目实战

    2024-03-19 11:54:03       34 阅读
  3. Spring Boot + Vue + Electron跨平台应用介绍

    2024-03-19 11:54:03       48 阅读
  4. Nginx线程池源码剖析

    2024-03-19 11:54:03       35 阅读
  5. es6 enum 多关联写法

    2024-03-19 11:54:03       43 阅读
  6. 【ES6】字符串新增方法

    2024-03-19 11:54:03       39 阅读
  7. Linux之scp命令的使用方法

    2024-03-19 11:54:03       43 阅读
  8. 愚人节礼物(C++)

    2024-03-19 11:54:03       47 阅读
  9. C# 循环

    C# 循环

    2024-03-19 11:54:03      38 阅读
  10. MySQL 运算符

    2024-03-19 11:54:03       40 阅读