You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

给定固定长度绳索 求二维平面可包围最大石头数量的算法求解

闭合绳索最多包围平面石头数问题

这是一道算法编程题:

二维平面上分布有若干石头,给定一段已知长度的绳索,求使用这段闭合绳索最多可以包围多少个石头?(绳索必须为闭合状态)

我最初认为这道题等价于在无向图中寻找长度不超过上限、包含节点数最多的环,BFS似乎是可行解法,但这个问题看起来属于NP-hard问题。

补充说明

举个例子:平面上共有5个石头,共有三种包围方案:黑色、红色、蓝色。每种方案的绳索长度是所有边的长度之和。
该问题等价于:从N个点中按顺序选出$x_1,...x_n$共n个点,满足总长度和 = $d(x_1,x_2)+d(x_2,x_3)+...+d(x_{n-1},x_n)+d(x_n,x_1) ≤ C$,其中n>1,求n的最大值。

参考解法

经过提示后,我发现该问题和无向图无关,它和从给定数组中选出若干元素和等于目标值的问题类似,但区别在于本题的结果和选择顺序相关,因此不能按照数组原有顺序选择。以下是我的解法,但仍存在大量重复搜索的问题,比如如果某符合条件的环有4个节点,我们会从4个节点分别出发重复搜索4次。

// 计算两点之间的欧氏距离
double d(const vector<double> a, const vector<double> b)
{
    return sqrt((a[0] - b[0])*(a[0] - b[0]) + (a[1] - b[1])*(a[1] - b[1]));
}

/*
递归搜索函数
参数说明:
array: 存储所有石头坐标的数组
target: 剩余可用的绳索长度
out: 当前已经选入路径的点
sum: 当前路径的总长度
ct: 目前搜索到的最大可包围石头数量
res: 用于调试时存储合法路径结果
visited: 标记已经被选入路径的点,避免重复选择
*/
void help(vector<vector<double>> array, double target, vector<vector<double>> &out, int &sum, int & ct, vector<vector<vector<double>>> &res, vector<bool> &visited)
{
    // 由于选择顺序会影响结果,需要从头遍历所有点,用visited跳过已选的点
    for (int i = 0; i < array.size(); i++) 
    {
        if (visited[i]) continue;
        else if (out.empty()) {
            out.push_back(array[i]); 
            visited[i] = true;
        }
        else
        {
            vector<double> last = out.back(), first = out.front();
            // 判断加入当前点后,闭合路径的总长度是否不超过绳索上限
            if (sum + d(array[i], last) + d(array[i], first) <= target)
            {
                out.push_back(array[i]);
                sum += d(array[i], last);
                ct = max(ct, (int)out.size());
                visited[i] = true;
                // 递归搜索下一个点,传入剩余可用长度
                help(array, target - d(array[i], last), out, sum, ct, res, visited);
                // 回溯,恢复上一层的状态
                out.pop_back();
                sum -= d(array[i], last);
                visited[i] = false;
            }
            else
            {
                res.push_back(out);
                return;
            }
        }
    }
}
int Path(vector<vector<double>> array, double target) {
    int sum = 0, ct = 0; 
    vector<vector<double>> out;
    vector<vector<vector<double>>> res;
    vector<bool> visited(array.size(), false);
    help(array, target, out, sum, ct, res, visited);

    return ct;
}

内容的提问来源于stack exchange,提问作者user6703592

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 06:54:04