天梯选拔赛题目

目录

区间选点

输入格式:

输出格式:

输入样例:

输出样例:

波兰表达式

输入格式:

输出格式:

输入样例:

输出样例:

 跳一跳 (升级版) 

输入:

输出:

范围:

社交集群

输入格式:

输出格式:

输入样例:

输出样例:

 田忌赛马 

输入格式:

输出格式:

输入样例:

输出样例:


区间选点

给定N个闭区间[ai,bi],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。 输出选择的点的最小数量。 位于区间端点上的点也算作区间内。

1<N<1e5

-1e9<ai≤bi≤1e9

输入格式:

第—行包含整数N,表示区间数。 接下来N行,每行包含两个整数a,bi,表示一个区间的两个端点。

输出格式:

一个整数

输入样例:

在这里给出一组输入。例如:

3
-1 1
2 4
3 5

输出样例:

在这里给出相应的输出。例如:

2

思路:首先这是个简单贪心问题。我们根据右端点从小到大排序,如果相等,则根据左端点从小到大排序,如果后一个左端点大于前一个右端点,则答案加一,注意答案初始化要为1。这与另一个经典的贪心问题之安排活动相似,安排活动是根据结束时间从小到大排序,如果相等则按开始时间从小到大排序。

#include<bits/stdc++.h>
using namespace std;
struct Point
{
    long long a,b;
}e[100100];
bool compare(Point x,Point y)
{
    return x.b<y.b;
    if(x.b==y.b)return x.a<y.a;
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    cin>>e[i].a>>e[i].b;
    sort(e+1,e+1+n,compare);
    int num=1;
    for(int i=2;i<=n;i++)
    {
        if(e[i].a>e[i-1].b)num++;
    }
    cout<<num;
    return 0;
}

波兰表达式

波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的波兰表示法为+ 2 3。波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的波兰表示法为* + 2 3 4。本题求解波兰表达式的值,其中运算符包括+ - * /四个。

输入格式:

输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数。

输出格式:

输出为一行,表达式的值。

输入样例:

* + 1.0 2.0 + 3.0 4.0

输出样例:

21.000000

注意:atof(),是C 语言标准库(stdlib.h)中的一个字符串处理函数,功能是把字符串转换成浮点数,并将其值返回为double。无法执行有效的转换,该函数将返回 0.000000。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
char vis[10];
double s()
{
    scanf("%s",vis);
    switch(vis[0])
    {
        case '+':return s()+s();
        case '-':return s()-s();
        case '*':return s()*s();
        case '/':return s()/s();
        default:return atof(vis);
    }
}
int main()
{
    printf("%lf",s());
    return 0;
}

 跳一跳 (升级版) 

我跳累了~😢

人活着本没有意义,但只有活着就会碰到很多有趣的事,就像你发现了花,而我发现了你一样。


这里有一段整数数组nums,你一开始处于下标为0的第一个元素处,请求出你最少跳几次能到达数组的末尾位置。

当你在i位置时可以跳跃到一下三个位置:

  • i + 1:i+1 < nums.length
  • i - 1:i-1 >= 0
  • j:nums[i] == nums[j]

输入:

第一行输入n表示nums的长度 第二行以空格分隔输入nums的每个元素

11
11 22 7 7 7 7 7 7 7 22 13

输出:

输出一行最小跳跃次数

3

范围:

  • 1 <= nums.length <= 5 * 104
  • -108<= nums[i] <= 108
#include<bits/stdc++.h>
using namespace std;
map<int,vector<int>>mp;
int n;
int date[100010],book[100010];
int minn=99999999;
void dfs(int present,int step)
{
    if(present==n)
    {
        if(step<minn)
        {
            if(step<minn)minn=step;
            return;
        }
    }
    if(step>=minn)return;
    if(present>1&&book[present-1]==0)
    {
        book[present-1]=1;
        dfs(present-1,step+1);
        book[present-1]=0;
    }
    if(present<n&&book[present+1]==0)
    {
        book[present+1]=1;
        dfs(present+1,step+1);
        book[present+1]=0;
    }
    if(mp[date[present]].size()>1)
    {
        for(auto v:mp[date[present]])
        {
            if(book[v]==0)
            {
                book[v]=1;
                dfs(v,step+1);
                book[v]=0;
            }
        }
    }


}
int main()
{
    cin>>n;
    for(int i=1; i<=n; i++)
    {
        cin>>date[i];
        mp[date[i]].push_back(i);
    }
    book[1]=1;
    dfs(1,0);
    cout<<minn;
    return 0;
}

社交集群

当你在社交网络平台注册时,一般总是被要求填写你的个人兴趣爱好,以便找到具有相同兴趣爱好的潜在的朋友。一个“社交集群”是指部分兴趣爱好相同的人的集合。你需要找出所有的社交集群。

输入格式:

输入在第一行给出一个正整数 N(≤1000),为社交网络平台注册的所有用户的人数。于是这些人从 1 到 N 编号。随后 N 行,每行按以下格式给出一个人的兴趣爱好列表:

Ki​: hi​[1] hi​[2] ... hi​[Ki​]

其中Ki​(>0)是兴趣爱好的个数,hi​[j]是第j个兴趣爱好的编号,为区间 [1, 1000] 内的整数。

输出格式:

首先在一行中输出不同的社交集群的个数。随后第二行按非增序输出每个集群中的人数。数字间以一个空格分隔,行末不得有多余空格。

输入样例:

8
3: 2 7 10
1: 4
2: 5 3
1: 4
1: 3
1: 4
4: 6 8 1 5
1: 4

输出样例:

3
4 3 1

思路:每一个人用第一个兴趣编号代表用户,将一个人的兴趣编号用并查集和并起来,这样有相同兴趣的人就被分在了一个组,然后遍历每一个人,查找他的兴趣的父亲节点,然后用一个计数数组技术便可以得到每个圈子有多少人,不为零的个数就是圈子个数。

#include<bits/stdc++.h>
using namespace std;
int fa[1010],book[1010],user[1010];
int findd(int x)
{
    if(fa[x]==x)return x;
    else
    {
        fa[x]=findd(fa[x]);
        return fa[x];
    }
}
void unionn(int x,int y)
{
    int dx=findd(x),dy=findd(y);
    if(dx==dy)return;
    else fa[dx]=dy;
}
bool compare(int a,int b)
{
    return a>b;
}
int main()
{
    for(int i=1;i<=1000;i++)
        fa[i]=i;
    int t;
    cin>>t;
    for(int i=1; i<=t; i++)
    {
        int k;
        char c;
        cin>>k>>c>>user[i];
        for(int j=1; j<k; j++)
        {
            int d;
            cin>>d;
            unionn(user[i],d);
        }
    }
    for(int i=1;i<=t;i++)
    book[findd(user[i])]++;
    int num=0;
    for(int i=1;i<=1000;i++)
    if(book[i]!=0)num++;
    cout<<num<<endl;
    sort(book+1,book+1+1000,compare);
    for(int i=1;i<=num;i++)
    {
        cout<<book[i];
        if(i!=num)cout<<" ";
    }
    return 0;
}

 田忌赛马 

田忌与齐王赛马,双方各有n匹马参赛,每场比赛赌注为200两黄金,现已知齐王与田忌的每匹马的速度,并且齐王肯定是按马的速度从快到慢出场,现要你写一个程序帮助田忌计算他最好的结果是赢多少两黄金。

说明: 为了简单起见,保证2n匹马的速度均不相同。

输入格式:

输入每组测试数据占3行,第一行是n(n<=1000),表示双方参赛马的数量,第2行n个正整数,表示田忌的马的速度,第3行n个正整数,表示齐王的马的速度.测试数据以“0”结束。

输出格式:

每组测试数据输出一行数据,表示田忌比赛的最好结果是赢多少两黄金。

输入样例:

3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0

输出样例:

200
0
0

思路:这是简单贪心问题,我们把田忌的马和齐王的马从大到小排个序

情况1:如果田忌最大的马比齐王最大的马快,则答案加200

情况2:如果田忌最慢的马比齐王最慢的马快,则答案加200

情况3∶如果田忌最慢的马比齐王最快的马慢,则答案减200(也就是用最慢的马去耗qw最快的马)

情况4:如果田忌最慢的马和齐王最快的马一样快,且不符合以上三种情况,那么肯定这2n匹马的速度相同,故不需要对答案做操作

#include<bits/stdc++.h>
using namespace std;
int a[1010],b[1010];//田忌,齐王
bool compare(int a,int b)
{
    return a>b;
}
int main()
{
    int n;
    cin>>n;
    while(n!=0)
    {
        for(int i=1; i<=n; i++)
            cin>>a[i];
        for(int i=1; i<=n; i++)
            cin>>b[i];
        sort(a+1,a+1+n,compare);
        sort(b+1,b+1+n,compare);
        int ans=0;
        int n1=1,n2=1,m1=n,m2=n;
       for(int i=1;i<=n;i++)
        {
            if(a[n1]>b[n2])
            {
                ans+=200;
                n1++;
                n2++;
            }
            else if(a[m1]>b[m2])
            {
               ans+=200;
               m1--;
               m2--;
            }
            else
            {
                if(a[m1]<b[n2])
                {
                    ans-=200;
                    m1--;
                    n2++;
                }
            }

        }
        cout<<ans<<endl;
        cin>>n;

    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值