中国矿业大学数据结构实验(4)
A 机器人王国的路径长度
题目描述
在一个机器人王国里,围绕首都分\(N\)层构建卫星城市。以首都为圆心,以路相连分出两个卫星城在第一个层,然后每个卫星城又有路相连分出两个卫星城在下一层,但每条路的长度不同。第\(N\)层的卫星城不再分出新的卫星城。现在人类只探知到所有直接相连的城市间的路程,你能计算某个卫星城到达首都的路程吗?
输入
第一行为\(N\),表示机器人王国里有\(N\)层卫星城,\(N\)最大为10。从第二行开始,共\(2^{N+1}-2\)行,每行分别是城市的代号到其分出的卫星城的代号和它们间的路程。 代号用若干个字母表示,直连路程最大为100。最后一行是某卫星城的代号。
输出
根据最后一行的卫星城代号,求该卫星城到首都的路程。
样例输入
2
A F 20
B D 100
G A 5
G B 10
A C 6
B E 30
D
样例输出
110
思路
建模:给你一颗\(N\)层完全二叉树,根节点已知(可以设为\(-1\)),求根到给定节点的路径长
需要记录两个信息:节点\(u\)的父亲\(fa\),边权\((u,fa)\),开一个结构体即可
struct edge
{
int fa;//父亲节点
int w; //边权
}
ACcode
#include<iostream>
#include<cmath>
using namespace std;
const int N = 15;
struct edge
{
int fa = -1,w;
}e[10000];
int toi(char c) { return c - 'A' + 1; }
int main()
{
int n, m;
cin >> n;
m = pow(2, n + 1) - 2;
cout << m << endl;
for (int i = 1; i <= m; i++)
{
int w;
char a, b;
cin >> a >> b >> w;
int u = toi(a), v = toi(b);
e[v] = { u,w };
}
int q, ans = 0;
char c; cin >> c;
q = toi(c);
while (q != -1)
{
ans += e[q].w;
q = e[q].fa;
}
cout << ans << endl;
return 0;
}
B 从源点开始的最短路径
题目描述
给你一个有向图的所有顶点有序对,顶点用\(1-n\)编号,每个有序对描述有向边,请编程求解从1到任意一个顶端\(i\)的最短路径长度。
输入
第一行是\(n\)和\(m\),分别表示顶点数\((n<100)\)和有向边数\((m<100)\)。
从第二行开始\(m\)行,对应三个数,前两个表示顶点有序对,第三个数表示边的权。
最后一行\(i\),表示要求解从1到顶点\(i\)的最短路径长度。
输出
从1到顶点\(i\)的最短路径长度。
样例输入
4 5
1 2 4
1 3 6
2 3 1
3 4 6
2 4 7
3
样例输出
5
思路
纯模板不解释
ACcode
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int N = 105;
const int inf = 0x3f3f3f3f;
struct edge {
int v, w;
};
vector<edge>e[N];
int n, m, a, b, c;
int d[N], vis[N];
void dijkstra(int s)
{
for (int i = 1; i <= n; i++) d[i] = inf;
d[s] = 0;
priority_queue<pair<int, int>>q;
q.push({ 0,s });
while (q.size())
{
auto t = q.top(); q.pop();
int u = t.second;
if (vis[u]) continue;
vis[u] = 1;
for (auto ed : e[u])
{
int v = ed.v, w = ed.w;
if (d[u] + w < d[v])
{
d[v] = d[u] + w;
q.push({ -d[v],v });
}
}
}
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
cin >> a >> b >> c;
e[a].push_back({ b,c }); //有向图
}
dijkstra(1);
int i; cin >> i;
cout << d[i] << endl;
return 0;
}
C 最少天数
问题描述:
现有一个工程项目,包含多个子任务。每个子任务有明确的前置任务和完成所需的天数。项目的开始节点为 A,结束节点为 Z。请计算完成整个工程所需的最短天数。
输入格式:
- 第一行包含两个整数
N和M,分别表示项目中的节点数(事件数)和子任务数。 - 接下来的
M行,每行包含三个信息:startNode endNode weight,表示从节点startNode到节点endNode的子任务需要weight天完成。
输出格式:
输出一个整数,表示完成整个工程所需的最短天数。
样例输入:
6 8
A B 3
A C 2
B D 2
B E 3
C E 4
D F 3
E F 2
F Z 1
样例输出:
9
思路
在DAG上拓扑排序,同时\(dp\),状态转移\(dp[u]=\max\{dp[v_i]+w(v_i,u)\}\)
ACcode
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
const int N = 1000;
struct edge
{
int v, w;
};
vector<edge> e[N];
int dp[N], din[N], vis[N];
int n, m, c;
char a, b;
int toi(char c) { return c - 'A' + 1; }
void topo(int s)
{
memset(dp, 0, sizeof dp);
queue<int> q;
q.push(s);
while (q.size())
{
int u = q.front();
q.pop();
for (auto ed : e[u])
{
int v = ed.v, w = ed.w;
din[v]--;
dp[v] = max(dp[v], dp[u] + w);
if (!din[v]) q.push(v);
}
}
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
cin >> a >> b >> c;
int u = toi(a), v = toi(b);
e[u].push_back({ v,c });
din[v]++;
}
topo(1);
cout << dp[toi('Z')];
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
ACcode
#include<bits/stdc++.h>
using namespace std;
const int N = 100;
int n,T,a[N];
int main()
{
cin >> T;
while(T--)
{
cin >> n;
for(int i = 1 ; i <= n ; i ++) cin >> a[i];
sort(a+1,a+n+1);
int t = a[1];
int rk = 1;
while(a[rk] == t && rk < n) rk ++;
if(a[rk] == t) cout << "NO" << endl;
else cout << a[rk] << endl;
}
return 0;
}
E 按十进制各位和排序
题目描述
对于给定的正整数序列,按照每个数的十进制形式各个位上的数之和从大到小排序,各个位上的数和相同的按照本身大小排序,大的在前,小的在后。
输入
第一行 1 个整数 n,表示序列的大小。( 0 < n ≤ 1000) 第二行 n 个正整数,表示序列的每个数,每个数不大于 100000000。
输出
输出按照题目要求排序后的序列。
样例输入
6
17 26 9 13 88 22
样例输出
88 9 26 17 22 13
ACcode
#include<bits/stdc++.h>
using namespace std;
const int N = 1005;
string a[N];
int n;
bool cmp(string a,string b)
{
int sum1 = 0 ,sum2 = 0;
for(int i = 0 ; i < a.size() ; i ++) sum1 += (a[i]-'0');
for(int i = 0 ; i < b.size() ; i ++) sum2 += (b[i]-'0');
if(sum1 != sum2) return sum1 > sum2;
else
{
if(a.size() != b.size()) return a.size() > b.size();
for(int i = 0 ; i < a.size(); i ++)
{
if(a[i] != b[i]) return a[i] > b[i];
}
return true;
}
}
int main()
{
cin >> n;
for(int i = 1 ; i <= n ; i ++) cin >> a[i];
sort(a+1,a+n+1,cmp);
for(int i = 1 ; i <= n ; i ++) cout << a[i] << " ";
return 0;
}

浙公网安备 33010602011771号