目录
A:合并果子
题目描述
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
例如有3种果子,数目依次为1,2,9。可以先将 1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为 12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。
输入
输入包括两行,第一行是一个整数n(1 <= n <= 10000),表示果子的种类数。第二行包含n个整数,用空格分隔,第i个整数ai(1 <= ai <= 20000)是第i种果子的数目。
输出
输出包括一行,这一行只包含一个整数,也就是最小的体力耗费值。输入数据保证这个值小于2^31。
样例输入
3
1 2 9
样例输出
15
#include <iostream>
#include <queue>
int main()
{
std::priority_queue<int, std::vector<int>, std::greater<int>> pri_que;
int count, num;
while (std::cin >> count)
{
while (count--)
{
std::cin >> num;
pri_que.push(num);
}
int sum = 0, temp_1, temp_2;
while (!pri_que.empty())
{
temp_1 = pri_que.top();
pri_que.pop();
if (pri_que.empty())
{
break;
}
temp_2 = pri_que.top();
pri_que.pop();
sum = sum + temp_1 + temp_2;
pri_que.push(temp_1 + temp_2);
}
std::cout << sum << std::endl;
}
}
B:村村通工程预算
题目描述
某市将启动村村通工程。初期规划在村与村之间修建一些乡村公路,使一个村到另一个村只要有公路可以到达。后期将逐步使相邻乡村公路直达,当然富裕的乡村将自己出资修建,领导们深知“要致富先修路”的道理,这另当别论。
初期规划的费用也是很可观的,领导们很重视预算,编程能力高超的您被聘请为进行编程进行计算村村通的最小费用。
输入
有若干个组测试数据。
每组测试数据的第1行是村的个数n及村庄之间可以修道路的道路数m。接着的m行是预算中每条道路的描述:每行上有3个整数u、v、c,分别是相邻两个村庄的编号和修通直达公路的费用,顶点编号从1开始。
输出
对每组测试数据,输出达到村村通公路的的最小费用。
样例输入
3 3
1 2 1
1 3 3
2 3 1
3 2
1 2 1
2 3 3
样例输出
2
4
#include <iostream>
#include <vector>
#define INF 10000000
int Prim_B(std::vector<std::vector<int>> arc, int n, int w)
{
int i, j, k, min, minDist = 0;
int lowcost[n], adjvex[n];
for (i = 1; i < n; i++)
{
lowcost[i] = arc[w][i];
adjvex[i] = w;
}
lowcost[w] = 0;
for (i = 1; i < n - 1; i++)
{
min = INF;
for (j = 1; j < n; j++)
{
if ((lowcost[j] != 0) && (lowcost[j] < min))
{
min = lowcost[j];
k = j;
}
}
minDist = minDist + lowcost[k];
lowcost[k] = 0;
for (j = 1; j < n; j++)
{
if (arc[k][j] < lowcost[j])
{
lowcost[j] = arc[k][j];
adjvex[j] = k;
}
}
}
return minDist;
}
int main()
{
int num_country, num_road;
while (std::cin >> num_country)
{
std::cin >> num_road;
std::vector<std::vector<int>> map_road(num_country + 1, std::vector<int>(num_country + 1, INF));
int i, j, dist;
for (int a = 1; a < num_road + 1; a++)
{
std::cin >> i >> j >> dist;
map_road[i][j] = dist;
map_road[j][i] = dist;
}
int min_prim = Prim_B(map_road, num_country + 1, 1);
std::cout<< min_prim<<std::endl;
}
}
C:最短距离
题目描述
给定一个无向图G=(V,E),以及一个起点S和一个终点T,请你计算S到T的最短距离。
输入
包含多组数据。每组数据第一行包含两个正整数n和m(0<n<200,0<m<1000),分别表示图中顶点数和边数。顶点分别以0~n-1编号。
接下来是m行道路信息。每一行有三个整数A、B、C(0£A、B<N,A¹B,0<C<10000),表示点A和点B之间有一条长度为C的边。
再接下一行有两个整数S、T(0£S,T<n),分别代表起点和终点。
输出
对于每组数据,请在一行里输出S到T的最短距离。如果不存在从S到T的路线,就输出-1.
样例输入
3 3
0 1 1
0 2 3
1 2 1
0 2
3 1
0 1 1
1 2
样例输出
2
-1
#include <iostream>
#include <vector>
#include <queue>
#define INF 100000
int Dijkstra(std::vector<std::vector<int>> arc, int n, int start_pos, int end_pos)
{
std::vector<int> minDist(n, INF);
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<std::pair<int, int>>> pri_que;
pri_que.push(std::make_pair(0, start_pos));
minDist[start_pos] = 0;
while (!pri_que.empty())
{
std::pair<int, int> temp = pri_que.top();
pri_que.pop();
int vartex = temp.second;
if (vartex == end_pos)
{
return temp.first;
}
if (minDist[vartex] < temp.first)
{
continue;
}
for (int i = 0; i < n; i++)
{
if (minDist[vartex] + arc[vartex][i] < minDist[i])
{
minDist[i] = minDist[vartex] + arc[vartex][i];
pri_que.push(std::make_pair(minDist[i], i));
}
}
}
return -1;
}
int main()
{
// 路线两端的顶点,x,y,权重,cost,顶点数量,n,边的数量m,起点,start_pos,终点end_pos
int x, y, cost, n, m, start_pos, end_pos;
while (std::cin >> n >> m)
{
std::vector<std::vector<int>> map_map(n, std::vector<int>(n, INF));
for (int i = 0; i < m; i++)
{
std::cin >> x >> y >> cost;
if (cost < map_map[x][y])
{
map_map[x][y] = cost;
map_map[y][x] = cost;
}
}
std::cin >> start_pos >> end_pos;
int result = Dijkstra(map_map, n, start_pos, end_pos);
std::cout << result << std::endl;
}
return 0;
}