大疆笔试8.16软件类B卷编程题

1,142 阅读3分钟

大疆笔试编程题C++
试卷名称: 软件类B卷
开始时间: 2020-08-16 19:00
笔试时长: 120 分钟
结束时间: 2020-08-16 21:00

第一题:最短路径Dijkstra

时间限制: 3000MS
内存限制: 589824KB
题目描述:
最近DJI发布了一款Robomaster S1机器人,小伙伴们都沉迷其中不能自拔。小J为了能够在竞速比赛中迅速获胜,他决定利用开发的优势,在里面植入一套最优化的寻路算法。
比赛规则如下: 在比赛场地内预先设置N个路标,路标编号从0到N-1,S1只能沿直线在两个有连接的路标之间移动(部分路标之间是没有连接的) 比赛场地内的S1机器人从编号为0的路标出发,然后裁判给出随机一个路标(从0到N-1号路标中随机挑选一个)作为终点路标,要求S1机器人以尽可能快的速度从0号路标达到终点路标,总路程用时最短者获胜。
裁判会确保从0号路标和随机挑选的终点路标之间肯定存在至少一条路径。 小J在比赛开始前就已经得知了路标的数量 、通道的数量(每两个可以直接连接的路标点为一个通道)以及小车在每个通道上移动需要的时间。他需要编写一套算法,以确保能够快速找到最短路径,并输出小车在该路径移动所需要的时间,你能帮他实现这套算法吗?


输入描述
第一行输入两个个正整数 N和 P,其中N表示路标的数量, P表示通道的数量。 (1 < N <= 200,  0 <= P <= N * (N - 1) / 2 )
接下来的P行,每行输入三个正整数 A, B, T,A表示起点路标的编号,B表示终点路标的编号,T表示路标A到路标B需要时间T(0 <= A, B <= N-1, 1 <= T <= 100)
最后一行输入一个正整数 X,表示裁判给出的终点路标编号 (0 =< X <= N)
输出描述
输出一个正整数,表示小车从0号路标到X号路标之间移动的最短用时

样例输入
4 5
0 1 15
1 2 15
0 3 50
1 3 30
2 3 10
3

样例输出
40
#include<iostream>
#include<vector>
#include<algorithm>
#include<limits.h>
using namespace std;

int main()
{
	int N, P;
	cin >> N >> P;
	// Dijkstra
	vector<vector<int>> G(N, vector<int>(N, INT_MAX)); // G[i][j]表示从vertex i到vertex j的edge长度
	vector<int> dp(N, INT_MAX); // dp[i]表示从vertex 0到vertex i的路径长度
	vector<bool> isvisit(N, false); // isvisit表示是否已经加入集合S
	// 已经加入集合S的点为已经确保dp[.]更新为最佳路径长度
	for (int i = 0; i < N; i++)G[i][i] = 0;
	dp[0] = 0;
	while (P--)
	{
		int a, b, t;
		cin >> a >> b >> t;
		G[a][b] = t;
		G[b][a] = t;
		if (a == 0) dp[b] = t;
		if (b == 0) dp[a] = t; 
	}
	for (int i = 0; i < N; i++) // 每次往集合S加入一个点,一共N点
	{
		int mins = INT_MAX, u = 0;
		// 选取当前未加入集合S的点中距离点0最近的点,记为u
		for (int j = 0; j < N; j++)
		{
			if (!isvisit[j] && mins > dp[j])
			{
				mins = dp[j];
				u = j;
			}
		}
		isvisit[u] = true; // 点u加入集合S
		// 比较从点0直接到点j与经过点u到点j的距离大小
		// 将较小值赋值给dp[j],即更新dp[j]
		for (int j = 0; j < N; j++)
		{
			if (!isvisit[j] && dp[j] > dp[u] + G[u][j])
			{
				dp[j] = dp[i] + G[u][j];
			}
		}
	}
	int X;
	cin >> X;
	cout << dp[X] << endl;
	return 0;
}

第二题:多重背包

时间限制: 3000MS
内存限制: 589824KB
题目描述:
有许多程序员都热爱玩游戏,而小J自称为游戏王,曾玩过几百种游戏,几乎所有能玩到的游戏大作都玩遍了。随着时间的推移,他发觉已经没有游戏可以让他玩了!于是他想改玩一些古老的游戏,以成为真正的“游戏王”。他希望在接下来的一段时间内将过去出的游戏全部玩一遍,但是毕竟时间有限,因此他感到很苦恼。于是他想到一个计划,他先将每个游戏标上一个成就值,同时对每个游戏都估算一个通关所需要的天数,他计划在未来X天内让自己玩游戏的成就达到最大,那么他应该怎么做计划呢?(假设每个游戏最多只计划玩一遍,而且每个游戏必须玩完通关才能取得成就值,且通关每个游戏最小时间单位是1天)
输入描述
第一行输入两个整数N和X,中间用空格隔开,其中N表示游戏的数目N(1<=N<=10),X表示计划玩游戏的总时间天数 (1<=X<=1000)。
第二行输入第1个游戏的成就值A1(0<=A1<=10000) 和 通关所需要花费时间B1天 (1<=Bi<=500) 中间用空格隔开。
第N+1行输入第N游戏的成就值An(0<=An<=10000) 和 通关所需要花费时间Bn天(1<=Bn<=500) 中间用空格隔开
输出描述
可以达到成就之和的最大值。
样例输入
2 2
10 1
20 2
样例输出
20
提示
输入样例二:
3 4
10 2
18 3
10 2
输出样例二:
20
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;


int main()
{
	// 多重背包
	int N, X; // N物品数量,X最大承重
	cin >> N >> X;
	vector<int> A; // A[i]表示游戏i的成就值(价值)
	vector<int> B; // B[i]表示游戏i的天数(承重)
	vector<int> dp(X+1, 0); // dp[i]表示承重为不大于i时的最大价值
	int n = N;
	while (n--)
	{
		int a, b;
		cin >> a >> b;
		A.push_back(a);
		B.push_back(b);
	}
	for (int i = 0; i < N; i++)
	{
		for (int j = X; j >= B[i]; j--)
        // for(int j=B[i];j<=X;j++) // 错误,会对同一物品重复加入背包
		{
			dp[j] = max(dp[j], dp[j - B[i]] + A[i]);
		}
        // dp[j] for all j in [0,X]
        // 表示截至第i件产品已做出背或不背的决策
        // 此时承重不超过j的最大价值
	}
	cout << dp[X] << endl;
	return 0;
}

第三题:单调栈

编程题3
时间限制: 3000MS
内存限制: 589824KB
题目描述:
小C平时最喜欢玩数字游戏,最近他碰到一道有趣的数字题,他和他的好朋友打赌,一定能在10分钟内解出这道题,成功完成,小C就可以得到好朋友送他的Switch游戏机啦,你能帮助小C赢得奖品吗?
题目是这样的:给定一个非负的、字符串形式的整形数字,例如“12353789”,字符串的长度也就是整形数字的位数不超过10000位,并且字符串不会以0开头,小C需要挑选出其中K个数字(K小于字符串的长度)并删掉他们,使得剩余字符组成新的整数是最小的。
输入描述
第一行输入一串纯数字形式的字符串,组成一个正整数
第二行输入一个正整数K (K < 字符串的长度)
输出描述
输出一个数字(字符串格式)

样例输入
71245323308
4
样例输出
1223308

提示
输入样例二:
1683212
3
输出样例二:
1212
输入样例三:
100
1
输出样例三:
0

leetcode 402. 移掉K位数字

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;


int main()
{
	// 贪心算法
    // 单调栈
	// 从头开始遍历
	// 如果当前数字比下一个大,删除当前数字
	int count = 0; // 已经删除数字个数
	string s;
	int K;
	cin >> s;
	cin >> K;
	int i = 0;
	while (i < s.size() - 1 && count < K)
	{
		if (s[i] > s[i + 1])
		{
			s.erase(i, 1);
			count++;
			int j = i;
			while (j > 0 && s[j - 1] > s[i])j--;
			i = j;
		}
		else
		{
			i++;
		}
	}
	while (count < K)
	{
		s.erase(s.end() - 1);
		count++;
	}
	int lft = 0;
	while (lft < s.size() - 1 && s[lft] == '0')lft++;
	cout << s.substr(lft) << endl;
	return 0;
}