目录
问题A:机器人王国里的路径长度
题目描述
在一个机器人王国里,围绕首都分N层构建卫星城市。以首都为圆心,以路相连分出两个卫星城在第一个层,然后每个卫星城又有路相连分出两个卫星城在下一层,但每条路的长度不同。第N层的卫星城不再分出新的卫星城。现在人类只探知到所有直接相连的城市间的路程,你能计算某个卫星城到达首都的路程吗?
输入
第一行为N,表示机器人王国里有N层卫星城,N最大为10。从第二行开始,共2N+1-2行,每行分别是城市的代号到其分出的卫星城的代号和它们间的路程。 代号用若干个字母表示,直连路程最大为100。最后一行是某卫星城的代号。
输出
根据最后一行的卫星城代号,求该卫星城到首都的路程。
样例输入
2
A F 20
B D 100
G A 5
G B 10
A C 6
B E 30
D
样例输出
110
#include<bits/stdc++.h>
using namespace std;
const int N=10000;
map<string,string>parent;
map<string,int>data;
int main()
{
int n;
cin>>n;
for(int i=0;i<pow(2,n+1)-2;i++)
{
string m,n;
int len;
cin>>m>>n>>len;
parent[n]=m;
data[n]=len;
}
string p;
cin>>p;
int ans=0;
while(parent.count(p))
{
ans+=data[p];
p=parent[p];
}
cout<<ans;
return 0;
}
问题B:从源点开始的最短路径
题目描述
给你一个有向图的所有顶点有序对,顶点用1~n编号,每个有序对描述有向边,请编程求解从1到任意一个顶端i的最短路径长度。
输入
第一行是n和m,分别表示顶点数(n<100)和有向边数(m<100)。
从第二行开始n行,对应三个数,前两个表示顶点有序对,第三个数表示边的权。
最后一行i,表示要求解从1到顶点i的最短路径长度。
输出
从1到顶点i的最短路径长度。
样例输入
4 5
1 2 4
1 3 6
2 3 1
3 4 6
2 4 7
3
样例输出
5
#include<bits/stdc++.h>
using namespace std;
const int N = 100;
int n,m;
int dist[N],g[N][N];
bool st[N];
int dijkstra(int ans)
{
memset(dist,0x3f,sizeof dist);
dist[1] = 0;
for(int i=0;i<ans-1;i++)
{
int t = -1;
for(int j=1;j<=ans;j++)
{
if(!st[j]&&(t==-1||dist[t]>dist[j]))
t = j;
}
for(int j = 1;j<=ans;j++)
{
dist[j] = min(dist[j],dist[t]+g[t][j]);
}
st[t] = true;
}
if(dist[ans] == 0x3f3f3f3f) return -1;
return dist[ans];
}
int main()
{
cin>>n>>m;
memset(g,0x3f,sizeof g);
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b] = min(g[a][b],c);
}
int popurse;
cin>>popurse;
int t = dijkstra(popurse);
cout<<t;
return 0;
}
问题C:最少天数
题目描述
有一项大的工程,工程中有许多前后依赖的子任务,每个子任务都规划了完成需要的天数,假设给出用字母表示的事件结点,整个工程的开始事件用A表示,工程结束事件用Z表示,用事件结点有序对表示一个子任务的开始和结束,并给出每个子任务完成需要的天数。请编程求解完成这个工程的最短天数。
输入
第一行是事件结点的个数N(N<26)和子任务数M。
从第二行开始M行,每行是子任务的开始事件和结束事件以及完成该子任务所需天数。
输出
完成该工程所需的最少天数。
样例输入
4 3
A B 6
B Z 2
A Z 5
样例输出
8
#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
#include <limits>
using namespace std;
// 定义图的边
struct Edge {
char destination;
int weight;
};
// 计算完成工程的最短天数
int calculateShortestTime(const unordered_map<char, vector<Edge>>& graph) {
unordered_map<char, int> inDegree;
unordered_map<char, int> earliestStartTime;
// 统计每个事件的入度
for (const auto& node : graph) {
char currentNode = node.first;
inDegree[currentNode] = 0;
earliestStartTime[currentNode] = -1; // 初始化最早开始时间为-1
}
for (const auto& node : graph) {
char currentNode = node.first;
for (const Edge& edge : node.second) {
char nextNode = edge.destination;
inDegree[nextNode]++;
}
}
// 初始化起点的最早开始时间为0
earliestStartTime['A'] = 0;
// 使用拓扑排序计算每个事件的最早开始时间
queue<char> q;
q.push('A');
while (!q.empty()) {
char currentNode = q.front();
q.pop();
auto it = graph.find(currentNode);
if (it == graph.end()) {
continue;
}
for (const Edge& edge : it->second) {
char nextNode = edge.destination;
int nextStartTime = earliestStartTime[currentNode] + edge.weight;
earliestStartTime[nextNode] = max(earliestStartTime[nextNode], nextStartTime);
if (--inDegree[nextNode] == 0) {
q.push(nextNode);
}
}
}
// 返回工程的最短天数
return earliestStartTime['Z'];
}
int main() {
int N, M;
cin >> N >> M;
unordered_map<char, vector<Edge>> graph;
// 读取子任务信息
for (int i = 0; i < M; ++i) {
char startNode, endNode;
int weight;
cin >> startNode >> endNode >> weight;
graph[startNode].push_back({ endNode, weight });
}
int shortestTime = calculateShortestTime(graph);
cout << shortestTime << endl;
return 0;
}
问题D:寻找第二小的数
题目描述
求n个整数中第二小的数。
相同的整数看成一个数。比如,有5个数分别是1,1,3,4,5,那么第二小的数就是3。
输入
输入包含多组测试数据。输入的第一行是一个整数C,表示有C组测试数据;
每组测试数据的第一行是一个整数n,表示本组测试数据有n个整数(2<=n<=10),接着一行是n个整数(每个数均小于100)。
输出
为每组测试数据输出第二小的整数,如果不存在第二小的整数则输出“NO”,每组输出占一行。
样例输入
3
2
1 2
5
1 1 3 4 5
3
1 1 1
样例输出
2
3
NO
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int c,i,n,a[11],d;
scanf("%d",&c);
while(c--)
{
d=0;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
for(i=0;i<n-1;i++)
if(a[i]!=a[i+1])
{
printf("%d\n",a[i+1]);
d++;
break;
}
if(d==0)
printf("NO\n");
}
return 0;
}
问题E:按十进制给各位排序
题目描述
对于给定的正整数序列,按照每个数的十进制形式各个位上的数之和从大到小排序,各个位上的数和相同的按照本身大小排序,大的在前,小的在后。
输入
第一行 1 个整数 n,表示序列的大小。( 0 < n ≤ 1000) 第二行 n 个正整数,表示序列的每个数,每个数不大于 100000000。
输出
输出按照题目要求排序后的序列。
样例输入
6
17 26 9 13 88 22
样例输出
88 9 26 17 22 13
#include <iostream>
using namespace std;
int sum(int n)
{
int s = 0;
while(n>0)
{
s+=n%10;
n/=10;
}
return s;
}
int main()
{
int i,j,t,n,a[1000],b[1000];
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i];
b[i] = sum(a[i]);
}
for(i=0;i<n-1;i++)
{
for(j=0;j<n-i-1;j++)
{
if((b[j] < b[j+1]) || ((b[j] == b[j+1]) && (a[j] < a[j+1])))
{
t = b[j];
b[j] = b[j+1];
b[j+1] = t;
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
for(i=0;i<n;i++)
cout<<a[i]<<" ";
return 0;
}
问题F:奇偶数的排序
题目描述
给你10个正整数,其中5个奇数、5个偶数,先递减排奇数,然后再递增排偶数。请编程实现。
输入
一行10个正整数(int类型范围)。
输出
先递减排5个奇数,然后再递增排5个偶数,各个数之间有一个空格间隔。
样例输入
1 2 3 4 5 6 7 8 10 9
样例输出
9 7 5 3 1 2 4 6 8 10
#include<iostream>
#include<algorithm>
#define N 10
using namespace std;
bool comp1(const int &a,const int &b){
return a>b;
}
bool comp2(const int &a,const int &b){
return a<b;
}
int main(){
int a[N];
int i;
while(cin>>a[0]>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6]>>a[7]>>a[8]>>a[9]){
int od=0,ev=0;
int odd[N],even[N];
for(i=0;i<N;i++){
if(a[i]%2==0){
even[ev++]=a[i];
}
else
odd[od++]=a[i];
}
sort(even,even+ev,comp2);
sort(odd,odd+od,comp1);
if(od){
cout<<odd[0];
for(int i=1;i<od;i++) cout<<' '<<odd[i];
for(int i=0;i<ev;i++) cout<<' '<<even[i];
cout<<endl;
}else {
cout<<even[0];
for(int i=1;i<ev;i++) cout<<' '<<even[i];
cout<<endl;
}
}
return 0;
}