SYNU天梯校选题解

原创不易,未经允许,请勿转载。

博客主页:https://blog.csdn.net/Edviv

谁是赢家

题目大意

某电视台的娱乐节目有个表演评审环节,每次安排两位艺人表演,他们的胜负由观众投票和 3 名评委投票两部分共同决定。规则为:如果一位艺人的观众票数高,且得到至少 1 名评委的认可,该艺人就胜出;或艺人的观众票数低,但得到全部评委的认可,也可以胜出。节目保证投票的观众人数为奇数,所以不存在平票的情况。本题就请你用程序判断谁是赢家。

输入格式

输入第一行给出 2 个不超过 1000 的正整数 PaPb,分别是艺人 a 和艺人 b 得到的观众票数。题目保证这两个数字不相等。随后第二行给出 3 名评委的投票结果。数字 0 代表投票给 a,数字 1 代表投票给 b,其间以一个空格分隔。

输出格式

按以下格式输出赢家: The winner is x: P1 + P2

其中 x 是代表赢家的字母,P1 是赢家得到的观众票数,P2 是赢家得到的评委票数。

输入样例

327 129

1 0 1

输出样例

The winner is a: 327 + 1

按照题目意思模拟即可,赢无非两种可能,一种就是观众票数多且得到最少一名评委认可或者得到全部评委认可即获胜。

#include <bits/stdc++.h>
using namespace std;
int c[5];
int main()
{
	int a,b;
	cin>>a>>b;
	for(int i = 0; i < 3; i++) cin>>c[i];
	int a1 = 0,b1 = 0;  //a1 a b1 = b
	for(int i = 0; i < 3; i++)
	{
		if(c[i]) b1++;
		else a1++;
	}
	if((a>b && a1) || (a<b &&a1==3))
	{
		printf("The winner is a: %d + %d\n",a,a1);
	}
	else printf("The winner is b: %d + %d\n",b,b1);
	return 0;
}

猜数字

题目大意

一群人坐在一起,每人猜一个 100 以内的数,谁的数字最接近大家平均数的一半就赢。本题就要求你找出其中的赢家。

输入格式

输入在第一行给出一个正整数 N(≤1e4)。随后 N 行,每行给出一个玩家的名字(由不超过 8 个英文字母组成的字符串)和其猜的正整数(≤ 100)。

输出格式

在一行中顺序输出:大家平均数的一半(只输出整数部分)、赢家的名字,其间以空格分隔。题目保证赢家是唯一的。

输入样例

7

Bob 35

Amy 28

James 98

Alice 11

Jack 45

Smith 33

Chris 62

输出样例

22 Amy

按照题意模拟即可,求一下平均数的一半,然后找距离这个平均数一半差值最小的即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 7;
struct node{
    double x;
    char name[10];
};
node a[maxn];
int main()
{
    double n;
    scanf(" %lf",&n);
    double tot = 0;
    for(int i = 0; i < n; i++)
    {
        scanf(" %s %lf",a[i].name,&a[i].x);
        tot += a[i].x;
    }
    double ave = tot/(n*2.0);
    double cha = 1000;
    int pos = 0;
    for(int i = 0; i < n; i++)
    {
        double t = fabs(a[i].x - ave);
        if(t < cha)
        {
            cha = t;
            pos = i;
        }
    }
    printf("%d %s\n",(int)ave,a[pos].name);
    return 0;
}

月饼

题目大意

月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。 注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有 3 种月饼,其库存量分别为 18、15、10 万吨,总售价分别为 75、72、45 亿元。如果市场的最大需求量只有 20 万吨,那么我们最大收益策略应该是卖出全部 15 万吨第 2 种月饼、以及 5 万吨第 3 种月饼,获得 72 + 45/2 = 94.5(亿元)。

输入格式

每个输入包含一个测试用例。每个测试用例先给出一个不超过 1000 的正整数 N 表示月饼的种类数、以及不超过 500(以万吨为单位)的正整数 D 表示市场最大需求量。随后一行给出 N 个正数表示每种月饼的库存量(以万吨为单位);最后一行给出 N 个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。

输出格式

对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后 2 位。

输入样例

3 20

18 15 10

75 72 45

输出样例

94.50

贪心思想,选择性价比最高的即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 7;
struct node{
    double a,b,c;
    bool operator < (const node &t)const{
        return c < t.c;
    }
};
node d[maxn];
int main()
{
    int n;
    double m;
    scanf(" %d %lf",&n,&m);
    for(int i = 1; i <= n; i++) scanf(" %lf",&d[i].a);  //has
    for(int i = 1; i <= n; i++) scanf(" %lf",&d[i].b);  //cost
    for(int i = 1; i <= n; i++) d[i].c = d[i].b/d[i].a;
    sort(d+1,d+1+n);
    
    //for(int i = n; i; i--) cout<<d[i].id<<" "<<d[i].c<<endl;
    
    double ans = 0;
    for(int i = n; i && m >= 0; --i)
    {
        if(d[i].a <= m) 
        {
            ans += d[i].b;
            m -= d[i].a;
        }
        else if(d[i].a > m)
        {
            ans += d[i].c*m;
            m = -1;
        }
    }
    printf("%.2f\n",ans);
    return 0;
}


旅游规划

题目大意

有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

输入格式

输入说明:输入数据的第 1 行给出 4 个正整数 NMSD,其中 N(2≤ N ≤500)是城市的个数,顺便假设城市的编号为 0~(N−1)M是高速公路的条数; S 是出发地的城市编号; D 是目的地的城市编号。随后的 M 行中,每行给出一条高速公路的信息,分别是:城市 1、城市 2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过 500。输入保证解的存在。

输出格式

在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

输入样例

4 5 0 3

0 1 1 20

1 3 2 30

0 3 4 10

0 2 2 20

2 3 1 20

输出样例

3 40

数据小直接 f l o y e d floyed floyed,最短路径一样则更新最小花费即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 507, INF = 0x3f3f3f3f;
int mp[maxn][maxn];
int vis[maxn][maxn];
int v[maxn][maxn];
int main()
{
    ios::sync_with_stdio(false); cin.tie(0);
    int n,m,s,e;
    cin>>n>>m>>s>>e;
    s++; e++;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++) mp[i][j] = INF;
    
    for(int i = 1; i <= m; i++)
    {
        int f, t, d, c;
        cin>>f>>t>>d>>c;
        f++; t++;
        mp[f][t] = mp[t][f] = d;
        vis[f][t] = vis[t][f] = 1;
        v[f][t] = v[t][f] = c;
    }
    
    
    for(int k = 1; k <= n; k++)
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                if(mp[i][j] > mp[i][k] + mp[k][j] && vis[i][j] && vis[i][k] && vis[k][j])
                {
                    mp[i][j] = mp[i][k] + mp[k][j];
                    int t = v[i][j];
                    v[i][j] += v[i][k] + v[k][j];
                    v[i][j] -= t;
                }
                else if(mp[i][j] == mp[i][k] + mp[k][j] && vis[i][j] && vis[i][k] && vis[k][j])
                {
                    int t = v[i][j];
                    if(t > v[i][k] + v[k][j])
                        v[i][j] = v[i][k] + v[k][j];
                }
            }
        }
    }
    cout<<mp[s][e]<<' '<<v[s][e]<<'\n';
    return 0;
}

寻宝路线

题目大意

在一个 mn 列方格矩阵中,每一个方格内摆放着价值不等的宝贝(价值可正可负),让小明感到好奇的是,从左上角到达右下角的所有可能路线中,能捡到宝贝的价值总和最大是多少?而且这种达到最大值的路线 又有多少条?【注意:只能从一个格子向下或向右走到相邻格子,并且走到的格子宝贝一定会被捡起。】

输入格式

第一行为整数 mn(均不大于 100 ),下一行开始会有一个 mn 列的整数方阵,对应方格矩阵中的宝贝价值(这些值的绝对值都不超过 500)。

输出格式

单独一行输出 2 个整数,分别为能捡到宝贝价值总和的最大值和达到最大值的路线数量, 2 个整数间隔一个空格。

输入样例

4 5

2 -1 6 -2 9

-3 2 5 -5 1

5 8 3 -2 4

5 2 8 -4 7

输出样例

26 3

寻找最大值就是一个简单的动态规划,想清楚状态即可。
1.状态表示 f [ i ] [ j ] : f[i][j]: f[i][j]表示第 i i i 行第 j j j 列的位置,属性表示权值。
2.状态转移:
第一列只能有上一行走过来,第一行只能由前一列走来
其余位置可以由前一行或者前一列走过来。

3.确定编码方式

第一行 f[i][j] = f[i][j-1] + a[i][j]
第一列 f[i][j] = f[i-1]j] + a[i][j]
其余位置 f[i][j] = max(f[i][j-1],f[i-1][j]) + a[i][j]

在这里插入图片描述
至于寻找方案可以写个 B F S BFS BFS 即可,不会请自行百度。
UVA 624 01背包输出方案问题题目链接
参考博客链接

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 110;
int f[maxn][maxn];
int a[maxn][maxn];
int vis[maxn][maxn];
int n,m;
struct node{
    int x,y;
};
vector<node> d[maxn][maxn];
queue<node> q;
int main()
{
    ios::sync_with_stdio(false); cin.tie(0);
    cin>>n>>m;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            cin>>a[i][j];
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            if(i == 1)
            {
                f[i][j] = f[i][j-1] + a[i][j];
                d[i][j].push_back({i,j-1});
            }
            else if(j == 1)
            {
                f[i][j] = f[i-1][j] + a[i][j];
                d[i][j].push_back({i-1,j});
            }
            else
            {
                if(f[i][j-1] > f[i-1][j])
                {
                    d[i][j].push_back({i,j-1});
                    f[i][j] = f[i][j-1] + a[i][j];
                }
                if(f[i][j-1] < f[i-1][j])
                {
                    d[i][j].push_back({i-1,j});
                    f[i][j] = f[i-1][j] + a[i][j];
                }
                if(f[i][j-1] == f[i-1][j])
                {
                    d[i][j].push_back({i,j-1});
                    d[i][j].push_back({i-1,j});
                    f[i][j] = f[i-1][j] + a[i][j];
                }
            }
        }
    }
    int ans = f[n][m], num = 1;
    for(int i = 0; i < d[n][m].size(); i++) q.push(d[n][m][i]);
    if(q.size() == 2) num++;
    while(!q.empty())
    {
        node to = q.front();
        q.pop();
        int tx = to.x;
        int ty = to.y;
        if(d[tx][ty].size() == 2) num++;
        for(int i = 0; i < d[tx][ty].size(); i++) q.push(d[tx][ty][i]);
    }
    cout<<ans<<" "<<num<<endl;
    return 0;
}

最长对称子串

题目大意

对给定的字符串,本题要求你输出最长对称子串的长度。例如,给定Is PAT&TAP symmetric?,最长对称子串为s PAT&TAP s,于是你应该输出11。

输入格式

输入在一行中给出长度不超过1000的非空字符串。

输出格式

在一行中输出最长对称子串的长度。

输入样例

Is PAT&TAP symmetric?

输出样例

11

在这里插入图片描述

两个指针,一个指向字符串首部,一个指向字符串尾部,当前匹配成功,判断一下是否到达终点,到达退出循环,否则临时指向 l l l 的指针后移,匹配失效看看边界问题,在边界内就保存一下当前最大回文串长度。时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

#include <bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false); cin.tie(0);
    string s;
    getline(cin,s);
    int n = s.size(), ans = 0;
    for(int i = 0; i < n; i++)
    {
        int t = i, j = n;
        for(; j >= t; j--)
        {
            if(s[t] == s[j]) 
            {
                if(j == t) break;
                else t++;
            }
            else if(j > t) t = i;
        }
        if(j <= t)
        {
            if(j == t) ans = max(ans,(t-i)*2 + 1);
            else ans = max(ans,(t-i)*2);
        }
    }
    cout<<ans<<endl;
    return 0;
}

拯救007

题目大意

在老电影“ 007之生死关头”( Live and Let Die)中有一个情节, 007被毒贩抓到一个鳄鱼池中心的小岛上,他用了一种极为大胆的方法逃脱 —— 直接踩着池子里一系列鳄鱼的大脑袋跳上岸去!(据说当年替身演员被最后一条鳄鱼咬住了脚,幸好穿的是特别加厚的靴子才逃过一劫。) 设鳄鱼池是长宽为 100 米的方形,中心坐标为 (0, 0),且东北角坐标为 (50, 50)。池心岛是以 (0, 0) 为圆心、直径 15米的圆。给定池中分布的鳄鱼的坐标、以及 007一次能跳跃的最大距离,你需要告诉他是否有可能逃出生天。

输入格式

首先第一行给出两个正整数:鳄鱼数量 N(≤100)和 007 一次能跳跃的最大距离 D。随后 N 行,每行给出一条鳄鱼的 (x,y) 坐标。注意:不会有两条鳄鱼待在同一个点上。

输出格式

如果 007 有可能逃脱,就在一行中输出 "Yes",否则输出 "No"

输入样例一

14 20

25 -15

-25 28

8 49

29 15

-35 -2

5 28

27 -29

-8 -28

-20 -35

-25 -20

-13 29

-30 15

-35 40

12 12

输出样例一

Yes

输入样例二

4 13

-12 12

12 12

-12 -12

12 -12

输出样例二

No

在这里插入图片描述
暴力搜索DFS

#include <cstdio>
#include <cmath>
#include <algorithm>
#define ll long long int
#define rep(i,a,b) for(auto i = (a); i <= (b); i++)
#define per(i,a,b) for(auto i = (a); i >= (b); i--)
using namespace std;
const int maxn = 1e3 +7;
struct node{
    int x, y;
};
node p[maxn];
int vis[maxn];
bool ok;
int n;
double d;

bool first(int x, int y)
{
    if((d + 7.5)*(d + 7.5) >= (x*x + y*y)) return true;
    return false;
}

bool Turn(int sx, int sy, int ex, int ey)  //当前点跳到下一个点
{
    if((ex - sx)*(ex - sx) + (ey - sy)*(ey - sy) <= d*d) return true;
    return false;
}

bool inbound(int x, int y)  //位置是否合法
{
    x = abs(x), y = abs(y);
    if(x + d >= 50 || y + d >= 50) return true;
    return false;
}

bool dfs(int i)
{
    vis[i] = true;
    if(inbound(p[i].x, p[i].y)) return true;
    else
    {
        rep(j, 1, n)
        {
            if(!vis[j] && Turn(p[i].x, p[i].y, p[j].x, p[j].y))  //第 i个位置跳到第j个位置
            {
                ok = dfs(j);
                if(ok) return true;
            }
        }
    }
    return false;
}

int main()
{
    scanf("%d %lf",&n,&d);
    rep(i, 1, n) scanf("%d%d",&p[i].x,&p[i].y);
    if(d >= 42.5) puts("Yes");
    else
    {
        rep(i, 1, n)
        {
            if(!vis[i] && first(p[i].x, p[i].y))
                ok = dfs(i);
                if(ok)
                {
                    puts("Yes");
                    return 0;
                }
        }
    }
    puts("No");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幸愉聊信奥

谢谢亲的支持,我会继续努力啦~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值