2023年SF-X【未来科技赛道-编程方向】半决赛 补题

答题序号题目名称分数当前状态得分通过率

1.

顺丰小哥分拣快递

10

通过

10

68%

2.

顺丰管理处罚系统

20

未通过

0

14%

3.

顺丰小哥送快递

30

未通过

0

9%

4.

顺丰主管调度

40

未通过

0

16%

明年再战吧,AK的大佬都是学了四五年的,半决赛前50名:进决赛+ 校招pass卡。(看了一下排名,总赛区前200名进决赛,一小时内50分就进了,)

 顺丰小哥分拣快递

顺丰小哥是顺丰的仓管员,他每天都需要对快递进行分拣。

我们用不同的字符表示快递的类型,共有小写字母、大写字母、数字三种类型。顺丰小哥需要把相同类型的快递分拣到一起。请你编写一个程序完成这个操作。

输入描述:

一个字符串,代表顺丰小哥拿到的所有快递。

保证每种类型的快递至少有一个。

字符串仅由大小写字母和数字组成,长度不超过200000。

输出描述:

一共输出三行字符串,代表分拣后的结果。不同字符串需要按照顺丰小哥拿到快递的顺序进行输出。

第一行输出小写字母类型的快递。

第二行输出大写字母类型的快递。

第三行输出数字类型的快递。

示例1

输入:

aBc3g4G

输出:

acg
BG
34

第一题签到题五分钟不用就做完了,but也只做了这一题。

#include<bits/stdc++.h>
using namespace std;
int main() {
    vector<char> v1;
    vector<char> v2;
    vector<char> v3;
    string s;
    cin >> s;
    for (int i = 0; s[i]; ++i) {
        if (s[i] >= 'a' && s[i] <= 'z') v1.emplace_back(s[i]);
        else if (s[i] >= 'A' && s[i] <= 'Z') v2.emplace_back(s[i]);
        else if (s[i] >= '0' && s[i] <= '9') v3.emplace_back(s[i]);
    }
    for (int i = 0; i < v1.size(); ++i)
        cout << v1[i];
    puts("");
    for (int i = 0; i < v2.size(); ++i)
        cout << v2[i];
    puts("");
    for (int i = 0; i < v3.size(); ++i)
        cout << v3[i];
    puts("");

    return 0;
}

顺丰管理处罚系统 

顺丰里面有一个处罚管理系统,为了管理处罚系统,请你帮忙实现如下函数:

List<HistoryResult> query(int pageNo, int pageSize) :查询处罚记录,记录按照id升序排序

List<HistoryResult> getByUserId(int userId) :查询某个用户的处罚记录,记录按照id升序排序

int punish(String operatorUserName, int userId, int punishStatus) : 处罚操作, 如果用户已经有被处罚了,新的处罚必须高于当前处罚等级才能生效,operatorUserName为执行处罚的人,userId为被处罚用户的编号

int relieve(String operatorUserName, int userId) : 解除当前处罚,operatorUserName为解除处罚的人,userId为被解除处罚用户的编号。若当前用户无处罚记录则该操作无效。解除处罚的status设置为0

只有有效的处罚或解除处罚操作,才会被记录id。这两种操作的返回值为该操作的id,从1开始自增。若操作为无效操作,返回-1

输入描述:

第一行输入一个N(2<N<=200000),代表操作个数

接下来的每2行代表1个操作,

每2行的第1行输入一个操作的英文名字,代表对应的操作

每2行的第2行输入操作对应的参数

输出描述:

对应每个查询操作,记录一个结果,最后统一输出所有处罚操作和解除处罚操作的返回值,你只需要完成函数即可,输出无需理会

示例1

输入:

7
punish
bob 5 3
punish
bob 5 1
relieve
alice 3
relieve
alice 5
query
1 20
query
2 20
getByUserId
5

输出:

1_5_bob_3
2_5_alice_0
1_5_bob_3
2_5_alice_0
1
-1
-1
2

说明:

前两行为query 1 20的输出,query 2 20没有输出。第3行和第4行为getByUserId 5的输出。最后4行依次为4次处罚/解除处罚操作的返回值。

示例2

输入:

4
punish
bob 5 1
punish
bob 5 3
relieve
alice 5
punish
bob 5 3

输出:

1
2
3
4

我是第一次碰到这种题,就是C++的自己写类什么什么的。由于我的C++学的是山寨版的,就是C+cin,cout+STL,所以这题涉及到知识盲区,等我暑假学了完整版的C++后,再肥来····

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

class HistoryResult
{
public:
	HistoryResult(int id, int userId, string operatorUserName, int status)
	{
		this->id = id;
		this->userId = userId;
		this->operatorUserName = operatorUserName;
		this->status = status;
	}

	int getId() const
	{
		return id;
	}

	int getUserId() const
	{
		return userId;
	}

	string getOperatorUserName() const
	{
		return operatorUserName;
	}

	int getStatus() const
	{
		return status;
	}

private:
	int id;
	int userId;
	string operatorUserName;
	int status;
};

class Main
{
public:

	/**
     * 查询处罚记录,记录按照id升序排序
     *
     * @param pageNo   第几页
     * @param pageSize 页数大小
     * @return 查询结果
     */
	vector<HistoryResult> query(int pageNo, int pageSize)
	{
	}

 	/**
     * 查询某个用户的处罚记录,记录按照id升序排序
     *
     * @param userId 用户
     * @return 处罚记录
     */
	vector<HistoryResult> getByUserId(int userId)
	{
	}

	/**
     * 处罚操作, 如果用户已经有被处罚了,新的处罚不能低于当前处罚等级才能生效
     *
     * @param operatorUserName 操作者的名字
     * @param userId           处罚的用户
     * @param punishStatus     处罚类型
     * @return 返回处罚的记录id, 处罚不成功返回-1
     */
	int punish(string operatorUserName, int userId, int punishStatus)
	{
	}

	 /**
     * 解除当前处罚
     *
     * @param operatorUserName 操作者的名字
     * @param userId           解除处罚的用户
     * @return 如果当前用户正在被处罚中,解除当前处罚,返回处罚记录id,如果用户没有被处罚,返回-1表示解除处罚非法
     */
	int relieve(string operatorUserName, int userId)
	{

	}
};

int main()
{
	Main main;
	int opNum;
	cin >> opNum;
	cin.ignore();
	vector<HistoryResult> printHistory;
	vector<int> printOperators;
	for (int i = 0; i < opNum; ++i)
	{
		string op;
		getline(cin, op);
		string data;
		getline(cin, data);
		if (op == "punish")
		{
			std::istringstream iss(data);
			std::string operatorUserName;
			int userId;
			int punishStatus;
			iss >> operatorUserName >> userId >> punishStatus;
			printOperators.push_back(main.punish(operatorUserName, userId, punishStatus));
		}
		else if (op == "relieve")
		{
			std::istringstream iss(data);
			string operatorUserName;
			int userId;
			iss >> operatorUserName >> userId;
			printOperators.push_back(main.relieve(operatorUserName, userId));
		}
		else if (op == "getByUserId")
		{
			std::istringstream iss(data);
			int userId;
			iss >> userId;
			vector<HistoryResult> results = main.getByUserId(userId);
			if (!results.empty())
			{
				printHistory.insert(printHistory.end(), results.begin(), results.end());
			}
		}
		else if (op == "query")
		{
			std::istringstream iss(data);
			int pageNo, pageSize;
			iss >> pageNo >> pageSize;
			vector<HistoryResult> results = main.query(pageNo, pageSize);
			if (!results.empty())
			{
				printHistory.insert(printHistory.end(), results.begin(), results.end());
			}
		}
		else
		{
			cout << "错误的输入" << endl;
		}
	}
	for (const HistoryResult &result : printHistory)
	{
		cout << result.getId() << "_" << result.getUserId() << "_"
			 << result.getOperatorUserName() << "_" << result.getStatus() << endl;
	}
	for (int operatorResult : printOperators)
	{
		cout << operatorResult << endl;
	}
	return 0;
}

顺丰小哥送快递

地图上有n个城市,m条道路。每个道路连接着两个城市。顺丰小哥需要将快递从1号城市运到号城市,
另外,顺丰小哥有一个魔法,他可以花费时间从一个城市传送到任意另一个城市。为了避免暴露自己会魔法的事实,他不会在起点和终点使用魔法(也不会作为魔法的目的地),且魔法最多只能使用一次。
顺丰小哥想知道,自己完成送快递至少需要多少时间?    

输入描述

第一行输出三个正整数n,m,x,代表城市数量、道路数量以及顺丰小哥使用魔法需要耗费的时间。
接下来的m行,每行输出三个正整数u,v,w,代表u号城市和v号城市有一条双向道路连接,且顺丰小哥使用该道路需要花费的时间为w。
1 <= n, m <= 10⁵

1 <= u, v <= n

1 <= x, w <= 10⁹

输出描述:

如果顺丰小哥无法完成运货,则输出-1。
否则输出最小需要花费的时间。

示例1

输入:

4 2 5
1 2 1
3 4 1

输出:

7

说明:

顺丰小哥先花费1的时间从1号城市走到2号城市,然后使用魔法传送到3号城市,之后再花费1的时间从3号城市走到4号城市。

示例2

输入:

4 3 5
1 2 1
3 4 1
2 3 2

输出:

4

说明:

顺丰小哥不需要使用魔法,花费4的时间即可。路线为1->2->3->4。

怎么说呢这题,应该是我感觉就差一步之遥就做出来了,就差一点点,然后看了一位大佬的思路就豁然开朗,和他想的是差不多:

1.如果1或者n没有邻接点,返回-1
2.使用魔法:取1邻接点最近点距离x1,n邻接点最近点距离x2,然后代价就是x1+x2+x魔法
3.不使用魔法:dijstra查1到n的最短距离,不通则为max_int 
返回使用魔法和不使用魔法中距离更短的那个

 这个分情况分的很好,第一种情况我想到了,主要是第二和第三种情况当时迷迷糊糊没有明确拆开来😟

#include<bits/stdc++.h>
using namespace std;
const int N = 100005;
typedef long long ll;
int n, m, u, v;
ll x, w, l1, l2;
ll dist[N];
bool vis[N];
struct edge {
	int to;
	ll w;
	edge(int a, ll b) { to = a, w = b; }
};
vector<edge> g[N];
struct node {
	int id;
	ll dis;
	node(int a, ll b) { id = a, dis = b; }
	bool operator < (const node& u) const { return dis > u.dis; }
};
int main() {
	cin >> n >> m >> x;
	for (int i = 1; i <= n; ++i) dist[i] = 10000000000;
	while (m--) {
		cin >> u >> v >> w;
		g[u].emplace_back(edge(v, w));
		g[v].emplace_back(edge(u, w));
	}
	//1.如果1或者n没有邻接点,返回-
	if (g[1].empty() || g[n].empty()) {
		cout << -1;
		return 0;
	}
	//2.使用魔法:取1邻接点最近点距离x1,n邻接点最近点距离x2,然后代价就是x1+x2+x魔法
	ll x1, x2;
	x1 = x2 = 0x3f3f3f3f;
	for (int i = 0; i < g[1].size(); ++i) {
		x1 = min(x1, g[1][i].w);
	}
	for (int i = 0; i < g[n].size(); ++i) {
		x2 = min(x2, g[n][i].w);
	}
	l1 = x1 + x2 + x;
	//3.不使用魔法:dijstra查1到n的最短距离,不通则为0x3f3f3f3f
	priority_queue<node> q;
	dist[1] = 0;
	q.emplace(node(1, dist[1]));
	while (q.size()) {
		node u = q.top(); q.pop();
		if (vis[u.id]) continue;
		vis[u.id] = 1;
		for (int i = 0; i < g[u.id].size(); ++i) {
			edge e = g[u.id][i];
			if (vis[e.to]) continue;
			if (dist[e.to] > u.dis + e.w) {
				dist[e.to] = u.dis + e.w;
				q.emplace(node(e.to, dist[e.to]));
			}
		}
	}
	l2 = dist[n];
	cout << min(l1, l2);
	return 0;
}

 分析错点:第一次错误是因为我没有用邻接表存,他的最大数据是要开g[n][n](n = 10⁵)会爆掉,后面改了,用邻接表存就直接百分之90多的测试点过了。第二次错误是因为我把int改成long long因为他的长度最大是10⁹多来几个边就会爆int所以换了long long。第三次又将dist数组的初值赋为0x3f3f3f3f改成1000000005就比10⁹多个5,结果只过了百分之80多的测试点。后面意识到自己傻蛋了应该更大点然后就赋值10的十次方就AC了。

太后悔了这题,会错的,当时比赛没做出,就是想不到,题目刷太少!

顺丰主管调度

顺丰主管将对他手下的兼职快递员们进行任务安排。
已知快递分为两种类型,第一种类型为同城快送,第二种类型为跨城运输。顺丰主管手下有n个兼职快递员,每个快递员的工资分别为ai,运送快递的顾客满意值为bi。快递员有两种类型:类型A只能送同城快运,类型B则可以送任意快递。
顺丰主管共有x个同城快送任务,y个跨城运输任务。他需要把这些快递派发给他手下的快递员,每个人最多只能接一个任务。顺丰主管想知道,在支付总工资尽可能小的情况下,最终的顾客满意值之和最大是多少?
注:任务必须全部接完。每个快递员只能接一个任务。

输入描述:

第一行输入四个正整数n, x, y,分别代表快递员数量和两种类型任务的数量。
接下来的n行,每行输入一个字符type和两个正整数ai, bi用来描述每个快递员的类型以及工资和顾客满意值。
1 <= n, x, y <= 10⁵
1 <= ai, bi <= 10⁹
保证type字符是'A'或者'B'。

输出描述:

如果无法接完全部任务,则输出-1。
否则一个整数,代表最终最大的顾客满意值。

示例1

输入:

3 1 1
A 2 5
B 2 3
A 3 7

输出:

8

说明:

选择第一个快递员做第一个类型的任务,第二个做第二个类型的任务,总工资为4,满意值之和为8。

请注意,如果选择第二个和第三个快递员,虽然能达成更高的满意度,但需要支付5的总工资,不符合要求。

示例2

输入:

2 1 1
A 2 300
A 9 1000

输出:

-1

说明:

两个快递员都是A类型,只能送同城快送,无法完成跨城运输任务。因此输出-1。

早知道先做第四题的 早知道先做第四题的 早知道先做第四题的 以为分数高 死磕第三题去了~~>_<~~

然后第一次提交的时候以为没有用long long所以还是错了一下 太不细心了 不然可以进决赛的😭

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, x, y;
char c;
ll a, b, ans;
struct node {
	ll a, b;
	char c;
	node(ll x, ll y, char z) { a = x, b = y, c = z; }
};
struct Rule {
	bool operator()(const node& n1, const node& n2)const {
		if (n1.a == n2.a) {
			if (n1.b == n2.b) {
				return n1.c < n2.c;
			}
			else return n1.b > n2.b;
		}
		else return n1.a < n2.a;
	}
};
multiset<node, Rule> st;
int main() {
	cin >> n >> x >> y;
	for (int i = 0; i < n; ++i) {
		cin >> c >> a >> b;
		st.insert(node(a, b, c));
	}
	for (auto e:st){
		if (e.c == 'A') {
			if (x) {
				x--;
				ans += e.b;
			}
		}
		else {
			if (y) {
				y--;
				ans += e.b;
			}
			else if (x) {
				x--;
				ans += e.b;
			}
		}
	}
	if (x != 0 || y != 0) {
		cout << -1;
	}
	else cout << ans;
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值