smu2024蓝桥杯训练1

A. [语言月赛 202401] 装满葡萄汁的酒杯 - 洛谷

题意:有五个容量分别为100,150,300,400,1000的酒杯,输入一个整数n,输出能装下n的最下的酒杯容量(保证n<=1000)

思路:贪心,数组从小到大排序,从小到大遍历,大于等于n就输出

代码:

#include<bits/stdc++.h>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll; 
typedef pair<int, int> PII; 
const int N = 2e5+10;
int n, m, k;
int a[5]={100,150,300,400,1000};

void sovle(){
    cin>>n;
    for(int i=0;i<5;i++){
        if(a[i]>=n){
            cout<<a[i];
            return;
        }
    }
}

int main()
{	
    //ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    
    while (t --){
        sovle();
    }

    return 0;
}

B. [蓝桥杯 2018 省 A] 航班时间 - 洛谷

题意:给出往返程的起飞和降落时间(如果后面有(+x),代表经过了x天),输出两地的飞行时间(如果有则带上时差,即往返程时长不一样)。

思路:用scanf读入更方便(因为奇葩的蓝桥杯数据),如果读入完时间后的下一个getchar读取到的是空格,说明有经过x天,用scanf("(+%d)",&x)来读取。实际上无论有没有时差,都输出往返时间的和/2都能得到正确答案

代码:

#include<bits/stdc++.h>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll; 
typedef pair<int, int> PII; 
const int N = 2e5+10;
int n;

void sovle(){
    int m=0, k=0,a,a1,b,b1,c,c1,d,d1,e,e1,f,f1;
    scanf("%d:%d:%d %d:%d:%d",&a,&b,&c,&d,&e,&f);
    if(getchar()==' '){
        scanf("(+%d)",&m);
    }
    m*=24;
    int sum=(d+m-a)*3600+(e-b)*60+(f-c);
    scanf("%d:%d:%d %d:%d:%d",&a1,&b1,&c1,&d1,&e1,&f1);
    if(getchar()==' '){
        scanf("(+%d)",&k);
    }
    k*=24;
    int num=(d1-a1+k)*3600+(e1-b1)*60+(f1-c1);
    int qum=(sum+num)/2;
    printf("%02d:%02d:%02d\n",qum/3600,qum%3600/60,qum%3600%60);
}

int main()
{	
    //ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    cin>>t;
    //getchar();
    while (t --){
        sovle();
    }
    return 0;
}

C. [语言月赛 202312] 铅球杯 - 洛谷

题意:给出n个人的id和值,k个字符串,如果有{?},则将{?}替换成id为?的值,最后输出字符串

思路:用一个结构体数组存入id和值,遍历字符串到{时,建一个新字符串w,不等于}时就w.push_back(),结束后遍历数组找到id为w的输出其值

赛时RE了,因为初始化结构体爆了(悲

更优的思路:用find和replace函数来查找和替换

replace函数用法:

代码:

#include<bits/stdc++.h>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll; 
typedef pair<int, int> PII; 
const int N = 2e5+10;
int n, m, k;
struct node{
    string name;
    int num;
}a[5005];

void sovle(){
    cin>>n>>m;
    //memset(a,0,sizeof(a));
    for(int i=0;i<n;i++){
        cin>>a[i].name>>a[i].num;
    }
    getchar();
    string s;
    for(int i=0;i<m;i++){
        getline(cin,s);
        for(int j=0;j<s.size();j++){
            if(s[j]=='{'){
                string q;
                j++;
                while(s[j]!='}'){
                    q.push_back(s[j]);
                    j++;
                }
                for(int k=0;k<n;k++){
                    if(q==a[k].name){
                        cout<<a[k].num;
                        break;
                    }
                }
            }
            else cout<<s[j];
        }
        cout<<endl;
    }
}

int main()
{	
    //ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    while (t --){
        sovle();
    }

    return 0;
}

优化版:

#include<bits/stdc++.h>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll; 
typedef pair<int, int> PII; 
const int N = 2e5+10;
int n,m;
map<string,string>v;

void sovle(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        string a,b;
        cin>>a>>b;
        v["{"+a+"}"]=b;
    }
    getchar();
    for(int j=0;j<m;j++){
        string s;
        getline(cin,s);
        for(const auto &[a,b]:v)
            while (s.find(a) != string::npos)
                s.replace(s.find(a),a.size(),b);
            
            cout<<s<<endl;
    }
}

int main()
{	
    //ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    //getchar();
    while (t --){
        sovle();
    }
    return 0;
}

D. [蓝桥杯 2023 省 B] 飞机降落 - 洛谷

题意:给出n架飞机的到达时间,可盘旋时间,降落所需时间。每一时刻最多只能有一架飞机在进行降落。请你输出YES或NO表示能否给出一个降落顺序方案让所有飞机安全降落

思路:数据非常小,可以暴力dfs枚举降落方案能否满足,时间复杂度(10*10!)。

对于方案能否成功,关键在于前一架飞机尽快落地,后一架飞机才能有更多的时间落地。

贪心地,如果前一架飞机到达时间+落地时间<=当前飞机的到达时间+盘旋时间,那么当前飞机就能降落,并且当前飞机的到达时间应该更新为max(前一架飞机到达时间+落地时间,当前飞机的到达时间),这样每一次都判断,有一个不符合就输出NO,都符合就输出YES

代码:

#include<bits/stdc++.h>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll; 
typedef pair<int, int> PII; 
const int N = 2e5+10;
int n,m;
bool b[15];
struct node{
    int t,d,l;
}a[15];

bool dfs(int x,int time){
    if(x>=n){
        return true;
    }
    for(int i=0;i<n;i++){
        if(!b[i]){
            b[i]=1;
            if(a[i].t+a[i].d<time){
                b[i]=0;
                return false;
            }
            int t=max(a[i].t,time)+a[i].l;
            if(dfs(x+1,t)){
                return true;
            }
            b[i]=0;
        }
    }
    return false;
}

void sovle(){
    cin>>n;
    memset(b,0,sizeof(b));
    for(int i=0;i<n;i++){
        cin>>a[i].t>>a[i].d>>a[i].l;
    }
    if(dfs(0,0)){
        cout<<"YES"<<endl;
    }
    else cout<<"NO"<<endl;
}

int main()
{	
    //ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    cin>>t;
    //getchar();
    while (t --){
        sovle();
    }
    return 0;
}

E. [蓝桥杯 2023 省 B] 接龙数列 - 洛谷

题意:对于一个整数数列,如果每个数的首位都等于上一个数的末位,则称该数列为接龙数列

(i>=2&&i<=n)。输入一个长度为n数列,询问最少要删除几个数才能使该数列成为接龙数列

思路:数据太大10^5,暴力做法会超时。考虑用线性dp的方法,dp[i]表示以i结尾的接龙数列的长度,状态转移方程:dp[u]=max(dp[x],dp[u]+1),x表示该数的首位,u表示该数的末位。

代码:

#include<bits/stdc++.h>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll; 
typedef pair<int, int> PII; 
const int N = 2e5+10;
int n,m,dp[10];

void sovle(){
    cin>>n;
    for(int i=0;i<n;i++){
        string s;
        cin>>s;
        dp[s[s.size()-1]-'0']=max(dp[s[s.size()-1]-'0'],dp[s[0]-'0']+1);
    }
    int max1=0;
    for(int i=0;i<=9;i++){
        max1=max(dp[i],max1);
    }
    cout<<n-max1;
}

int main()
{	
    //ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    //getchar();
    while (t --){
        sovle();
    }
    return 0;
}

F. [蓝桥杯 2018 国 B] 调手表 - 洛谷

题意:一个小时有n分钟,每次可以选择让当前时间增加1或者k分钟,询问调到其他分钟最多需要操作多少次(分钟大于等于n时%n)

思路:bfs搜索到达所有时间需要多少层,如果已经访问过的时间就剪枝掉。头疼在怎么表示在第几层。可以用一个数组b[i]表示到达i这个时间的层数,每次搜索都step让step=b[i],b[(i+1)%n]=b[i]+1(下一层),b[(i+m)%n]=b[i]+1

代码:

#include<bits/stdc++.h>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll; 
typedef pair<int, int> PII; 
const int N = 2e5+10;
int n, m, k,max1,step,b[100005];
bool a[100005];

int bfs(int x){
    int sum=0;
    int u=0,w=0;
    a[x]=1;
    int step=1;
    queue<int>v;
    v.push(x);
    while(!v.empty()&&sum!=n-1){
        int i=v.front();
        v.pop();
        step=b[i];
        if(!a[(i+1)%n]){
            a[(i+1)%n]=1;
            b[(i+1)%n]=b[i]+1;
            v.push((i+1)%n);
        }
        if(!a[(i+m)%n]){
            a[(i+m)%n]=1;
            b[(i+m)%n]=b[i]+1;
            v.push((i+m)%n);
        }
    }
    return step;
}

void sovle(){
    cin>>n>>m;
    max1=max(max1,bfs(0));
    cout<<max1;
}

int main()
{	
    ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    while (t --){
        sovle();
    }

    return 0;
}

G.  [蓝桥杯 2023 省 A] 更小的数 - 洛谷

题意:输入一个只含数字的字符串,可以选择任意长度的子字符串num翻转为num1,如果num>num1,则答案数+1,输出答案总数

思路:区间dp,dp[l][r]表示下标l-r的子字符串能否满足条件,如果s[l]<s[r],dp[l][r]=1

如果s[l]==s[r],dp[l][r]=dp[l+1][r-1],如果s[l]>s[r],dp[l][r]=0

为了更新状态,需要从最后开始选取子串

代码:

#include<bits/stdc++.h>
#define endl '\n'
//#define int long long
using namespace std;
typedef long long ll; 
typedef pair<int, int> PII; 
const int N = 2e5+10;
int n, m, k,max1,step,dp[5005][5005],sum;

void sovle(){
    string s;
    cin>>s;
    for(int i=s.size()-1;i>=0;i--){
        for(int j=i;j<s.size();j++){
            //if(j==i) continue;
            if(s[j]<s[i]) dp[i][j]=1;
            else if(s[i]==s[j]) dp[i][j]=dp[i+1][j-1];
            else dp[i][j]=0;
            if(dp[i][j]){
                sum++;
            }
        }
    }
    cout<<sum;
}

int main()
{	
    ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    //cin>>t;
    while (t --){
        sovle();
    }

    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值