当前位置: 首页 > 知识库问答 >
问题:

算法难题:允许所有站在同一条线上的人相互交流的最小成本

殳自怡
2023-03-14

我有一个无法解决的算法设计难题。

谜题的公式是这样的:有N个人站在一条数字线上,每个人都可能站在该线上的任何整数上。多个人可以站在同一个号码上。对于任何两个人能够相互交流,他们之间的距离应小于K。目标是移动他们,使两个人中的每一对能够相互交流(可能通过其他人)。换句话说,我们需要移动它们,使相邻两个人之间的距离小于K。

问题:总移动次数的最小值是多少?这感觉就像是贪婪算法家族或动态规划。任何提示都将不胜感激!

共有2个答案

蒙勇
2023-03-14

这是一个用Java编写的贪婪算法,但我不知道它是否在所有情况下都给出了最优解。此外,它更像是一个概念证明,还有一些优化的空间。

这是基于这样一个事实,即两个相邻的人之间的距离不得超过K,下一个相邻的人之间的距离不得超过2K,以此类推。在每一步中,我们都会移动“最违反这些约束”的人。有关此计算的详细信息,请参见方法calcForce

package so;

import java.util.Arrays;

public class Main {

    public static void main(String args[]) {
        int[] position = new int[] {0, 0, 5, 11, 17, 23};
        int k = 5;

        solve(position, k);
    }

    private static void solve(int[] position, int k) {
        if (!sorted(position)) {
            throw new IllegalArgumentException("positions must be sorted");
        }
        int[] force = new int[position.length];
        int steps = 0;
        while (calcForce(position, k, force)) {
            int mp = -1;
            int mv = -1;
            for (int i = 0; i < force.length; i++) {
                if (mv < Math.abs(force[i])) {
                    mv = Math.abs(force[i]);
                    mp = i;
                }
            }
            System.out.printf("move %d to the %s%n", mp, force[mp] > 0 ? "right" : "left");
            if (force[mp] > 0) {
                position[mp]++;
            } else {
                position[mp]--;
            }
            steps++;
        }
        System.out.printf("total: %d steps%n", steps);
    }

    private static boolean calcForce(int[] position, int k, int[] force) {
        boolean commProblem = false;
        Arrays.fill(force, 0);
        for (int i = 0; i < position.length - 1; i++) {
            for (int j = i + 1; j < position.length; j++) {
                int f = position[j] - position[i] - (j - i) * k;
                if (f > 0) {
                    force[i] += f;
                    force[j] -= f;
                    commProblem = true;
                }
            }
        }
        return commProblem;
    }

    private static boolean sorted(int[] position) {
        for (int i = 0; i < position.length - 1; i++) {
            if (position[i] > position[i+1]) {
                return false;
            }
        }
        return true;
    }
}
景光赫
2023-03-14

我们可以在O(n)中执行以下操作:

计算以可接受的距离将所有人移动到peoplei的右侧朝向peoplei的成本:

costRight(A[i]) = costRight(A[i+1]) + (A[i+1] - A[i] - k + 1) * count of people to the right

K = 3;  A = { 0,  3, 11, 17, 21}
costRight = {32, 28, 10,  2,  0}

计算以可接受的距离将人i左侧的所有人移动到人i的成本:

costLeft(A[i]) = costLeft(A[i-1]) + (A[i] - A[i-1] - k + 1) * count of people to the left

K = 3;  A = { 0,  3, 11, 17, 21}
costLeft  = { 0,  1, 13, 25, 33}
costRight = {32, 28, 10,  2,  0}

既然我们有了来自两个方向的成本,我们可以在O(n)中这样做:

minCost = min(costRight + costLeft) for all A[i]
minCost = min(32 + 0, 28 + 1, 13 + 10, 25 + 2, 33 + 0) = 23

但有时这还不够:

K = 3;  A = { 0,  0,  1,  8,  8}

      carry:     -2  -4       3
costLeft  = { 0,  0,  0, 11, 11}

      carry: -3   5      -2
costRight = { 8,  8,  8,  0,  0}

最佳值既不是11也不是8。通过实现最大的节约来测试当前的最佳状态:

move 1 to 2, cost = 1

K = 3;  A = { 0,  0,  2,  8,  8}

      carry:     -2  -2     -10
costLeft  = { 0,  0,  0, 10, 10}

      carry: -2          -2
costRight = { 6,  6,  6,  0,  0}

minCost = 1 + min(0 + 6, 0 + 6, 0 + 6, 10 + 0, 10 + 0) = 1 + 6 = 7

不太确定如何有效地公式化。

 类似资料:
  • 我有一个横跨各种多边形的线串,存储为GeoJsons。我想在每个多边形区域内将线条分割成单独的部分。然而,我还没能做到这一点。这是我到目前为止的一个可复制的例子: 然后我尝试通过多边形分割直线,如下所示: 但我得到了以下输出,这似乎不正确: 我期望有三条线,一条存在于正方形多边形内,然后两条分别存在于多边形外。

  • 我有一个geopandas数据框,其中包含几个从lat、lon点数据创建的线串。对于所有直线交点,我需要在每个直线串中找到距离该交点最近的点。 因此,如果dataframe中的两条线相交,我需要在每个linestring中找到距离该相交点最近的点。我使用itertools找到了所有可能的交叉点,这些交叉点与本文中公认的答案类似:https://gis.stackexchange.com/quest

  • 我正在尝试使用MinCostFlow或工具解决一个工程问题。有一个带有管道和多个供应阀的机械分配系统。这些阀门需要连接到用户。起初,我试图用匈牙利算法来解决这个问题,但后来我意识到,这并不考虑通过路径的流。 节点0-4是消费者,节点4-7是供应阀,节点8和9是管道。我在每个消费者身上放了一个“供应”,以显示它期望的流量。我在最后放了一个水槽,以将供应从系统中取出。并非所有消费者都有相同的需求。我们

  • 主要内容:Min-Max算法的工作人工智能中的最小最大算法: Mini-max算法是一种递归或回溯算法,用于决策和博弈论。它为玩家提供了一个最佳的动作,假设对手也在玩最佳状态。 Mini-Max算法使用递归来搜索游戏树。 Min-Max算法主要用于AI中的游戏。如Chess,Checkers,tic-tac-toe,go和各种拖车玩家游戏。该算法计算当前状态的最小极大决策。 在该算法中,两个玩家玩游戏,一个叫做MAX,另一个叫做M

  • 问题内容: 我可以一次发送到的最大数据大小HttpURLConnection是Tomcat多少?请求大小是否有限制? 问题答案: maxPostSize 容器FORM URL参数解析将处理的POST的最大大小(以字节为单位)。可以通过将此属性设置为小于或等于0的值来禁用该限制。如果未指定,则将该属性设置为2097152(2兆字节)。 另一个限制是: maxHttpHeaderSize请求和响应HT

  • 我遇到了一个问题,我的 Linux EC2 实例无法执行任何出站(ping、卷曲、yum 更新、wget、跟踪路由等),除非我的 VPC ACL 入站规则集中有一个允许所有流量的规则。 我的安全组和VPC都有出站规则,允许所有流量访问所有内容。 附加到实例的安全组入站列表如下所示: VPC入站列表看起来像这样(规则200就是我说的规则): 如果我删除允许所有流量的入站规则(规则 200),则我无法