【贪心法】黑白连线问题

问题描述:
给定直线上 2 n 2n 2n 个点的序列 P [ 1 , 2 , … , 2 n ] P[1,2,… ,2n] P[1,2,,2n],每个点 P [ i ] P[i] P[i] 要么是白点(用数字 1 1 1 表示)要么是黑点(用数字 0 0 0 表示),其中共有 n n n 个白点和 n n n 个黑点,相邻两个点之间距离均为 1 1 1,请设计一个算法将每个白点与一黑点相连,使得连线的总长度最小。

黑白连线问题示例答案
例如,图中有 4 4 4 个白点和 4 4 4 个黑点,以图中方式相连,连线总长度为 1 + 1 + 1 + 5 = 8 1+1+1+5=8 1+1+1+5=8


贪心法:

思路1:
每遇到一个未被连接点,就向后寻找第一个(最近的)不同的点。
这个思路时间复杂度较高、空间复杂度较低。

思路2:
(1)维护一个黑点栈和白点栈;
(2)按顺序遍历每一个点,如果遇到一个白点,就查看当前黑点栈是否为空,非空的话就将将该白点与黑点栈顶黑点连接(因为栈是先入先出,所以栈顶黑点就是离该白点最近的未连接的黑点);遇到黑点也做类似的操作。
这个思路时间复杂度较低、空间复杂度较高。


思路2的C++实现:

//
//  main.cpp
//  ConnectBlackAndWhitePoint
//
//  Created by 胡昱 on 2021/12/31.
//

#include <iostream>
#include <stack>
using namespace std;

int main(int argc, const char * argv[]) {
    // 共m组测试数据
    int m;
    cin >> m;
    while((m--) > 0) {
        // 输入黑白点的数量n,即共有2*n个点
        int n;
        cin >> n;
        
        // 创建点数组points并输入点
        int* points = new int[2*n];
        for(int pi = 0; pi < 2 * n; ++pi) {
            cin >> points[pi];
        }
        
        // 创建黑白点栈
        stack<int> whitePoints;
        stack<int> blackPoints;
        
        // 初始化结果
        int result = 0;
        
        // 开始贪心算法
        for(int pi = 0; pi < 2 * n; ++pi) {
            // 如果是白色的点
            if(points[pi] == 0) {
                // 如果没有黑点待分配,就将这个白点入栈,等一个最近的黑点来挑它
                if(blackPoints.empty()) {
                    whitePoints.push(pi);
                }
                // 如果黑点栈中有未分配的黑点,就选择栈顶元素(也就是最近的黑点)
                else {
                    result += (pi - blackPoints.top());
                    blackPoints.pop();
                }
            }
            // 如果是黑色的点
            else {
                // 如果没有白点待分配,就将这个黑点入栈,等一个最近的白点来挑它
                if(whitePoints.empty()) {
                    blackPoints.push(pi);
                }
                // 如果白点栈中有未分配的白点,就选择栈顶元素(也就是最近的白点)
                else {
                    result += (pi - whitePoints.top());
                    whitePoints.pop();
                }
            }
        }
        
        // 输出结果并释放资源
        cout << result << endl;
        delete [] points;
    }
    return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python最短连线问题是指在给定的一组点中,找到两个点之间的最短路径。该问题可以使用图论算法解决,其中点表示图中的节点,边表示两个节点之间的距离。以下是使用Python解决最短连线问题的示例代码: ```python import math def distance(p1, p2): """计算两个点之间的距离""" x = p2[0] - p1[0] y = p2[1] - p1[1] return math.sqrt(x**2 + y**2) def shortest_path(points): """找到连接给定点的最短路径""" n = len(points) # 构建邻接矩阵 graph = [[0] * n for i in range(n)] for i in range(n): for j in range(i + 1, n): dist = distance(points[i], points[j]) graph[i][j] = dist graph[j][i] = dist # Dijkstra算法找到最短路径 dist = [float('inf')] * n dist[0] = 0 visited = [False] * n for i in range(n): # 找到距离最小的节点 min_distance = float('inf') min_index = -1 for j in range(n): if not visited[j] and dist[j] < min_distance: min_distance = dist[j] min_index = j visited[min_index] = True # 更新最短距离 for j in range(n): if not visited[j] and graph[min_index][j] != 0 and dist[min_index] + graph[min_index][j] < dist[j]: dist[j] = dist[min_index] + graph[min_index][j] # 返回距离最短的路径 return dist[-1] # 测试用例 points = [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)] print(shortest_path(points)) # 输出:4.242640687119285 ``` 在上面的示例中,我们首先定义了一个`distance`函数来计算两个点之间的距离。然后,我们使用邻接矩阵来表示给定点之间的距离,并使用Dijkstra算法来找到最短路径。最后,我们返回距离最短的路径。在测试用例中,我们使用了一组包含5个点的点集,并找到了连接它们的最短路径。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值