RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1412900
Accepted
sepera_okeq
sepera_okeq
Asked:2022-07-23 18:21:22 +0000 UTC2022-07-23 18:21:22 +0000 UTC 2022-07-23 18:21:22 +0000 UTC

查找元素之间的最小长度总和

  • 772

鉴于我们必须达到所有点,我真的不明白如何最好地实现找到最小长度总和的算法。

任务的本质:

我们有n个顶点,还有一个数组a等于n,是一个数,这就是点之间的距离。我们需要能够找到所有长度的最小总和,同时我们至少学习所有点 1 次。

在此处输入图像描述

例子:

我们n = 3还有一个数组(n 个元素)a = { 1, 2, 3 },其中a[0]是 1 和 2 之间a[1]的距离,是 2 和 3 之间的距离,a[2]这就是 3 和 1 之间的距离。

事实证明,选项是这样的,我们只取长度1 - 2和2 - 3,这会捕获所有点,同时给出等于 3 的最小长度总和。

在此处输入图像描述

示例#2: 为了更好地理解,我将举一个更复杂的示例。我们n = 6还有一个数组a = { 1, 2, 5, 1, 1, 6 },其中a[0]是1到2a[1]的距离,是2到3a[2]的距离,这是3到4a[3]的距离,这是4到5a[4]的距离,这是5到6的距离,a[5]这是 6 和 1 之间的距离。

事实证明,选项是这样的,我们只取长度1 - 2, 2 - 3, 4 - 5,5 - 6这会捕获所有点,同时给出等于 5 的最小长度总和。 在此处输入图像描述

在此处输入图像描述

您能建议在这种情况下进行的最佳方法吗?我尝试了贪心算法,但它不起作用,因为有一个错误。如果可能的话,如果有伪代码会很好......

c++
  • 2 2 个回答
  • 82 Views

2 个回答

  • Voted
  1. Chorkov
    2022-07-23T22:42:33Z2022-07-23T22:42:33Z

    表示 L(i,k) - 使用编号从 i 到 k-1 (含)的边,接触从第 i 个到第 k 个(含)顶点的最佳边集。搜索这样一个集合的决定,我们通过解决较短片段的问题来表达:L(i,k) = min{ L(i,k-1)+a[k-1] , L(i, k-2)+a[k-1] }其中 是两个集合的最小值,由元素的权重之和计算得出。有了线性段的解,我们可以表示完整循环的解:L_all = min{ L(1,n), L(2,n-1) + a[n] }.

    解决方案:

    #include <iostream>
    #include <functional>
    #include <type_traits>
    #include <vector>
    
    using a_t = std::vector<double>;
    using L_t = std::vector<size_t>;
    
    // добавляем элемент в конец вектора.
    L_t push_back( L_t L, size_t i )
    {
        L.push_back(i);
        return L;
    }
    
    // длинна множества ребер L, при весах a.
    int L_len( const a_t& a, const L_t& L )
    {
        double summ = 0;
        for(auto i : L)
            summ += a[i];
        return summ;
    }
    
    L_t L_min( const a_t& a, L_t L1 , L_t L2 )
    {
        return (L_len(a,L1)<L_len(a,L2)) ? L1 : L2;
    }
    
    L_t L( const a_t& a, size_t i, size_t k )
    {
        std::vector<L_t> L_ij(k+1);
        L_ij[i+1] = {i};
        L_ij[i+2] = {i, i+1};
        for( size_t j=i+3; j<=k; ++j )
            L_ij[j] = L_min( a,
                             push_back( L_ij[j-1] , j-1),
                             push_back( L_ij[j-2] , j-1) );
        return L_ij[k];
    }
    
    L_t solve( const a_t& a )
    {
        size_t n = a.size();
        return L_min( a,
                      L(a, 0, n-1 ),
                      push_back( L(a, 1, n-2 ) , n-1 )
                      );
    }
    
    int main()
    {
        for(auto i : solve({1,2,5,1,1,6}) )
            std::cout<<i<<std::endl;
    }
    

    去掉数组L_ij(只存储前面两个元素就够了),优化(可以优化为O(n)而不是O(n^2))留给题主。

    • 0
  2. Best Answer
    sepera_okeq
    2022-08-18T09:54:49Z2022-08-18T09:54:49Z

    最后,我确实找到了解决方案。为简化起见,我把它作为一个关于动物的问题,但这两个问题的含义是相同的。

    /**
    * Задача:
    * Дано n зверей, так-же дан массив a, где число - количество денег для кормежки двух зверьков.
    * n = 3
    * 1 2 3 -> 3
    * a1 = 1 (расстояние между точкой 1 и 2)
    * a2 = 2 (расстояние между точкой 2 и 3)
    * a3 = 3 (расстояние между точкой 3 и 1)
    * 
    * 3 - ответ.
    */
    
    #include <iostream>     // std::cin, std::cout
    #include <vector>       // std::vector
    #include <algorithm>    // std::find
    #include <string>       // std::string
    
    struct itemT;           // Храним данные о зверьках.
    struct itemL;           // Храним данные о стоимости кормешки рядом двух зверьков.
    
    using namespace std;    // in std namespace
    
    /**
    * Структура для хранения зверьков.
    * 
    * Включает в себя имя, стоимость кормешки с предыдущим 
    * и стоимость кормешки с зверьком впереди.
    */
    struct itemT
    {
        string name;
        itemL* prev;
        itemL* next;
    };
    
    /**
    * Структура для хранения стоимости кормешки двух рядом стоящих зверьков.
    *
    * Включает в себя имя ребра, стоимость кормешки,
    * указатели на первого зверька и следущего зверька.
    */
    struct itemL
    {
        string name;
        int cost;
        itemT* first;      
        itemT* second;
    };
    
    /**
    * Структура для хранения резульататов поиска оптимального решения 
    * с сохранением порядка кормешки.
    */
    struct varData
    {
        vector<string> seq;
        int cost;
    
        varData(vector<string> seqData, int costData)
        {
            seq = seqData;
            cost = costData;
        };
    };
    
    
    /**
    * Класс для удобной работы с массивом зверушек.
    */
    class LoopedReadOnlyArrayClass
    {
        itemT* arrayItem_T;
        int lengthArrayValue;
    
    public:
        /**
        * Конструктор, принимающий массив обьектов и размер массива.
        */
        LoopedReadOnlyArrayClass(itemT* items, int n) 
        {
            arrayItem_T = new itemT[n];
            for (int i = 0; i < n; i++)
                arrayItem_T[i] = items[i];
            lengthArrayValue = n;
        }
    
        /**
        * Метод для получения обьекта по данному индексу.
        */
        itemT get(int i) 
        {
            return arrayItem_T[i % lengthArrayValue];
        }
    
        /**
        * Метод для получения размера массива.
        */
        int length() 
        {
            return lengthArrayValue;
        }
    };
    
    
    int main()
    {
    
        setlocale(LC_ALL, "ru");
    
        /**
        * Получаем данные о количестве зверушек.
        */
        int n;
        cin >> n;
    
        /**
        * Получаем данные о стоимости кормешки.
        */
        int* a = new int[n];
        for (int i = 0; i < n; i++)
        {
            cin >> a[i];
        }
    
        /**
        * Трансформируем в удобную форму хранения данных.
        */
        itemT* arrayAnimal = new itemT[n];
        itemL* arrayAnimalCostLength = new itemL[n];
    
        cout << "Отображаю стоимость кормешки..." << endl;
    
        for (int i = 0; i < n; i++)
        {
            if (i == (n - 1))
            {
                arrayAnimalCostLength[i].name = "l" + std::to_string(i + 1);
                arrayAnimalCostLength[i].cost = a[i];
                arrayAnimalCostLength[i].first = &arrayAnimal[i];
                arrayAnimalCostLength[i].second = &arrayAnimal[0];
    
                cout << "CostLenght: " << "[ name:" << arrayAnimalCostLength[i].name << " cost:" << arrayAnimalCostLength[i].cost << " first: " << i+1 << " sec: " << 1 << " ]" << endl;
            }
            else
            {
                arrayAnimalCostLength[i].name = "l" + to_string(i + 1);
                arrayAnimalCostLength[i].cost = a[i];
                arrayAnimalCostLength[i].first = &arrayAnimal[i];
                arrayAnimalCostLength[i].second = &arrayAnimal[i + 1];
    
                cout << "CostLenght: " << "[ name:" << arrayAnimalCostLength[i].name << " cost:" << arrayAnimalCostLength[i].cost << " first: " << i+1 << " sec: " << i + 2 << " ]" << endl;
            }
    
        }
    
    
        cout << "\n\nОтображаю животных..." << endl;
    
        for (int i = 0; i < n; i++)
        {
            if (i == (n - 1))
            {
                arrayAnimal[i].name = to_string(i+1);
                arrayAnimal[i].next = &arrayAnimalCostLength[i];
                arrayAnimal[i].prev = &arrayAnimalCostLength[0];
    
                cout << "Animal: " << "[ name:" << arrayAnimal[i].name << " next:" << i + 1 << " prev:" << 1 << " ]" << endl;
            }
            else
            {
                arrayAnimal[i].name = to_string(i+1);
                arrayAnimal[i].next = &arrayAnimalCostLength[i];
                arrayAnimal[i].prev = &arrayAnimalCostLength[i + 1];
    
                cout << "Animal: "  << "[ name:" << arrayAnimal[i].name << " next:" << i+1 << " prev:" << i + 2 << " ]" << endl;
            }
        }
        /*
        * Трансформируем данные и используем удобный обьект,
        * для работы с данным массивом зверушек и их стоимости кормешки.
        */
        LoopedReadOnlyArrayClass* arrAdvanced = new LoopedReadOnlyArrayClass(arrayAnimal, n);
    
        /**
        * Вектор для хранения данных о результатах поиска оптимального процесса кормешки.
        */
        vector<varData> variants = {};
    
        /**
        * Проверяем варианты...
        */
        for (int i = 0; i < arrAdvanced->length(); i++) 
        {
            vector<string> seq = {};
            vector<string> feeded = {};
            int cost = 0;
    
            for (int j = 0; j < arrAdvanced->length(); j++) 
            {
                itemT element = arrAdvanced->get(i + j);
    
                if ((find(feeded.begin(), feeded.end(), element.name) != feeded.end())) 
                {
                    continue;
                }
    
                cost += element.next->cost;
    
                feeded.push_back(element.next->first->name);
                feeded.push_back(element.next->second->name);
    
                seq.push_back(element.next->name);
            }
            variants.push_back({ seq, cost }); // Заносим данные в вектор.
    
            //Если нужно вывести все варианты, раскоментируйте этот код.
            //for (auto i : seq)
            //    cout << i << ' ';
            //cout << " Cost:" << cost << endl;
        }
    
        /**
        * Ищем среди вариантов данных самый лучший вариант.
        */
        int minCost = INT_MAX;
        vector<string> varDataItem;
        for (int i = 0; i < variants.size(); i++)
        {
            if (variants[i].cost < minCost)
            {
                minCost = variants[i].cost;
                varDataItem = variants[i].seq;
            }
        }
    
        cout << "\n\nРезультат:" << endl;
    
        for (auto i : varDataItem)
            cout << i << ' ';
        cout << " Стоимость: " << minCost << endl;
    
        return 0;
    }
    

    我还在JS中发布了代码:

    let a = { name: "a", prev: null, next: null };
    let b = { name: "b", prev: null, next: null };
    let c = { name: "c", prev: null, next: null };
    let d = { name: "d", prev: null, next: null };
    let e = { name: "e", prev: null, next: null };
    let f = { name: "f", prev: null, next: null };
    
    let l1 = { name: "l1", cost: 1, first: a, second: b };
    let l2 = { name: "l2", cost: 2, first: b, second: c };
    let l3 = { name: "l3", cost: 3, first: c, second: d };
    let l4 = { name: "l4", cost: 4, first: d, second: e };
    let l5 = { name: "l5", cost: 5, first: e, second: f };
    let l6 = { name: "l6", cost: 6, first: f, second: a };
    
    /////
    
    a.prev = l6;
    a.next = l1;
    
    b.prev = l1;
    b.next = l2;
    
    c.prev = l2;
    c.next = l3;
    
    d.prev = l3;
    d.next = l4;
    
    e.prev = l4;
    e.next = l5;
    
    f.prev = l5;
    f.next = l6;
    
    /////
    
    class LoopedReadOnlyArray {
        #array;
    
        constructor(array) {
            this.#array = array;
        }
    
        get(i) {
            return this.#array[i % this.#array.length];
        }
    
        length() {
            return this.#array.length;
        }
    }
    
    /////
    
    let arr = new LoopedReadOnlyArray([ a, b, c, d, e, f ]);
    
    /////
    
    const variants = [];
    
    for (let i = 0; i < arr.length(); i++) {
        let seq = [];
        let feeded = [];
        let cost = 0;
    
        for (let j = 0; j < arr.length(); j++) {
            const element = arr.get([i + j]);
    
            if (feeded.includes(element.name)) {
                continue;
            }
    
            cost += element.next.cost;
    
            feeded.push(element.next.first.name);
            feeded.push(element.next.second.name);
    
            seq.push(element.next.name);
        }
    
        variants.push({ seq, cost });
    }
    
    console.log(variants);
    

    日志:

    [
      { seq: [ 'l1', 'l3', 'l5' ], cost: 9 },
      { seq: [ 'l2', 'l4', 'l6' ], cost: 12 },
      { seq: [ 'l3', 'l5', 'l1' ], cost: 9 },
      { seq: [ 'l4', 'l6', 'l2' ], cost: 12 },
      { seq: [ 'l5', 'l1', 'l3' ], cost: 9 },
      { seq: [ 'l6', 'l2', 'l4' ], cost: 12 }
    ]
    
    • 0

相关问题

  • 编译器和模板处理

  • 指针。找到最小数量

  • C++,关于枚举类对象初始化的问题

  • 函数中的二维数组

  • 无法使用默认构造函数创建类对象

  • C++ 和循环依赖

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5