双一次算法作业hhhhhhhhh

目录

A:合并果子

B:村村通工程预算

C:最短距离


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;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值