热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何将N个物体均匀的放入N个相邻移动的地方

如何将 N 个物体均匀的放入 N 个相邻移动的地方原文:https://www . geeksforgeeks . org/如何

如何将 N 个物体均匀的放入 N 个相邻移动的地方

原文:https://www . geeksforgeeks . org/如何通过相邻移动将 n 个对象平均放置到 n 个位置/

假设有 N 个对象不均匀地分布在 N 个容器中。您可以将一个对象从一个容器移动到相邻的容器,这被认为是一次移动。什么策略可以最大限度地减少移动次数,从而保持时间复杂度为 0(N)?
示例:

例 1。假设您有 5 个容器,填充为:
1,2,1,1,0
您将需要三次移动来将一个对象从第二个容器传递到最后一个- >,从第二个移动到第三个,然后移动到第四个,最后移动到第五个:
1,1,2,1,0
1,1,1,2,0
1,1,1,1
示例 2。现在更复杂一点。
假设你有 5 个容器,所有对象都在最后一个容器中:
0,0,0,0,5
显然,你会从右向左移动:
0,0,0,1,4
0,0,1,0,4
0,1,0,0,4
1,0,0,0,4
1,0,0,1,3
1,0,1,0,3
所有物体都在中间:
0,0,5,0,0
看起来没错:
0,1,4,0,0
1,0,4,0,0
1,1,3,0,0
1,1,2,1,0
1,1,2,0,1
1,1,1,1,1
需要 6 次移动

这个问题弱弱地提醒了一个所谓的鸽巢或狄利克雷原理–n 个物品放入 m 个容器中,用 n > m,那么至少一个容器必须包含一个以上的物品。因此它出现在标题中。
进场听起来相当琐碎:沿着集装箱排从头到尾移动,如果你遇到一个空集装箱,把它装满,如果你遇到一个有几个物体(不止一个)的集装箱,尽量把量减少到只有一个。
更准确地说,一个人必须保持一个有太多对象的容器队列和另一个空位置队列,并使用它们来传递对象。显然,由于我们试图一有可能就传递对象,所以在我们做了所有可能的运动后,每一步都会有一个队列变空。
再详细一点:
每次遇到空的地方,我们都会检查有多个物体的容器队列中是否有东西,如果有,就拿一个物体把空的地方填满。如果没有,将这个空位置添加到队列中。
每次遇到人满为患的集装箱,都要检查空位的队列是否有东西,如果有,尽量把当前集装箱的物品尽可能多的放入这些空集装箱,从它们的队列中取出。如果没有空的,将过度拥挤的集装箱推到满集装箱的队列中。
过度拥挤集装箱的队列中有成对的数字:多余物品的位置和数量。空容器的队列只保留位置的数字,因为它们是空的。
如果输入是以对象 A 的坐标数组的形式提供的,首先将其重组为每个位置的数量数组。
这个问题可以不止一个维度,就像启发了这篇文章的编码挑战 Selenium 2016 一样。但是因为维度是独立的,所以每个维度的结果只是被总结以得到最终的答案。
余数问题的完整实现包括最终答案取模 10^9+7.
示例:

Input :
Coordinates of objects are
X = [1, 2, 2, 3, 4] and array Y = [1, 1, 4, 5, 4]
Output :
5
Input :
X = [1, 1, 1, 1] and array Y = [1, 2, 3, 4]
Output :
6
Input :
X = [1, 1, 2] and array Y = [1, 2, 1]
Output :
4

注:还有另一种方法,可能会在另一篇文章中介绍,灵感来自于《余度未来移动性挑战》中一个更难的问题。包括以下步骤:


  • 从每个位置减去 1,现在我们争夺所有 0,而不是所有 1

  • 将数组切割成片段,例如在每个片段中,对象的移动都是在一个方向上,每个片段的开头和结尾都可以去掉零。样品:1,0,-1,0,-2,2 切成 1,0,-1 和-2,2。切割点由前缀和的零发现

  • 计算每个碎片的第二个积分。那是前缀从左到右的前缀。最正确的值是移动量。样本序列:1,0,-1。前缀是 1,1,0。第二个前缀是 1,2,2。这个片段的答案是 2(从 0 到 2 的两次移动)

  • 结果是所有片段结果的总和

最后执行第一种方式:

卡片打印处理机(Card Print Processor 的缩写)

#include
#include
using namespace std;
#define MODULO 1000000007
/* Utility function for one dimension
unsigned long long solution(vector& A)
Parameters: vector& A - an array of numbers
of objects per container
Return value: How many moves to make all containers
              have one object */
unsigned long long solution(vector& A)
{
    // the final result cannot be less than
    // zero, so we initiate it as 0
    unsigned long long res = 0;
    // just to keep the amount of objects for future usage
    const unsigned int len = (unsigned int)A.size();
     // The queue of objects that are ready for move,
     // as explained in the introduction. The queue is
     // of pairs, where the first value is the index
     // in the row of containers, the second is the
     // number of objects there currently.
    queue > depot;
     // The queue of vacant containers that are ready
     // to be filled, as explained in the introduction,
     // just the index on the row, since they are
    // empty - no amount, zero is meant.
    queue depotOfEmpties;
    // how many objects have coordinate i
    vector places(len, 0);
    // initiates the data into a more convenient way,
    // not coordinates of objects but how many objects
    // are per place
    for (unsigned int i = 0; i         places.at(A.at(i) - 1)++;
    }
    // main loop, movement along containers as
    // explained in the introduction
    for (unsigned int i = 0; i         // if we meet the empty container at place i
        if (0 == places.at(i)) {
            // we check that not objects awaiting
            // to movement, the queue of objects
            // is possible empty
            if (depot.empty()) {
                 // if true, no object to move, we
                 // insert the empty container into
                 // a queue of empties 
                depotOfEmpties.push(i);
            }
            // there are some object to move, take
            // the first from the queue  
            else {
                // and find how distant it is
                unsigned int distance = (i - depot.front().first);
                // we move one object and making
                // "distance" moves by it
                res += distance;
                // since the result is expected MODULO
                res = res % MODULO;
                // now one object left the queue
                // for movement, so we discount it
                depot.front().second--;
                 // if some elements in the objects
                 // queue may loose all objects, 
                while (!depot.empty() && depot.front().second <1) {
                    depot.pop(); // remove all them from the queue
                }
            }
        }
        // places.at(i) > 0, so we found the current
        // container not empty
        else {
            // if it has only one object, nothing must
            // be done
            if (1 == places.at(i)) {
                // so the object remains in its place,
                // go further
                continue;            
            }
            // there are more than one there, need
            // to remove some
            else {
                // how many to remove? To leave one
                unsigned int pieces = places.at(i) - 1;
                // how many empty places are awaiting to fill
                // currently? Are they enough to remove "pieces"?
                unsigned int lenEmptySequence = depotOfEmpties.size();
                // Yes, we have places for all objects
                // to remove from te current 
                if (pieces <= lenEmptySequence) {
                    // move all objects except one
                    for (unsigned int j = 0; j                         // add to the answer and apply MODULOto
                        // prevent overflow
                        res = (res + i - depotOfEmpties.front()) % MODULO;
                        // remove former empty from the queue of empties
                        depotOfEmpties.pop();
                    }
                }
                // empty vacancies are not enough or absent at all
                else {
                    for (unsigned int j = 0; j                         // fill what we can
                        res = (res + i - depotOfEmpties.front()) % MODULO;
                        // and remove filled from the vacancies queue 
                        depotOfEmpties.pop();
                    }
                    // since we still have too many objects in
                    // this container, push it into the queue for
                    // overcrowded containers
                    depot.push(pair(i,
                                        pieces - lenEmptySequence));
                }
            }
        }
    }
    // the main loop end
    return res; // return the result
}
/* Main function for two dimensions as in
   Codility problem
int solution(vector& A, vector& B)
Parameters:
 vector& A - coordinates x of the objects
 vector& B - coordinates y of the objects
Return value:
 No. of moves to make all verticals and horizontals
 have one object
*/
int solution(vector& A, vector& B)
{
    unsigned long long res = solution(B);
    res += solution(A);
    res = res % MODULO;
    return (int)res;
}
// test utility for the driver below
#include
void test(vector& A, vector& B, int expected,
         bool printAll = false, bool dOnotPrint= true)
{
    int res = solution(A, B);
    if ((expected != res && !doNotPrint) || printAll) {
        for (size_t i = 0; i             cout <        }
        cout <        for (size_t i = 0; i             cout <        }
        cout <        if (expected != res)
            cout <<"Error! Expected: " <        else
            cout <<"Expected: " <    }
    cout <<" Result: " <}
// Driver (main)
int main()
{
    int A4[] = { 1, 2, 2, 3, 4 };
    int B4[] = { 1, 1, 4, 5, 4 };
    vector VA(A4, A4 + 5);
    vector VB(B4, B4 + 5);
    test(VA, VB, 5);
    int A0[] = { 1, 1, 1, 1 };
    int B0[] = { 1, 2, 3, 4 };
    VA = vector(A0, A0 + 4);
    VB = vector(B0, B0 + 4);
    test(VA, VB, 6);
    int A2[] = { 1, 1, 2 };
    int B2[] = { 1, 2, 1 };
    VA = vector(A2, A2 + 3);
    VB = vector(B2, B2 + 3);
    test(VA, VB, 4);
    // square case
    int A3[] = { 1, 2, 3, 1, 2, 3, 1, 2, 3 };
    int B3[] = { 1, 1, 1, 2, 2, 2, 3, 3, 3 };
    VA = vector(A3, A3 + 9);
    VB = vector(B3, B3 + 9);
    test(VA, VB, 54);
    // also
    int A5[] = { 7, 8, 9, 7, 8, 9, 7, 8, 9 };
    int B5[] = { 7, 7, 7, 8, 8, 8, 9, 9, 9 };
    VA = vector(A5, A5 + 9);
    VB = vector(B5, B5 + 9);
    test(VA, VB, 54);
    int A6[] = { 1, 1, 2, 3 };
    int B6[] = { 1, 2, 3, 4 };
    VA = vector(A6, A6 + 4);
    VB = vector(B6, B6 + 4);
    test(VA, VB, 3);
    test(VB, VA, 3);
    int A7[] = { 1, 1, 3, 5, 5 };
    int B7[] = { 1, 5, 3, 1, 5 };
    VA = vector(A7, A7 + 5);
    VB = vector(B7, B7 + 5);
    test(VA, VB, 4);
    test(VB, VA, 4);
    // smaller square case
    int A8[] = { 1, 2, 1, 2 };
    int B8[] = { 1, 1, 2, 2 };
    VA = vector(A8, A8 + 4);
    VB = vector(B8, B8 + 4);
    test(VA, VB, 8);
    int A9[] = { 3, 4, 3, 4 };
    int B9[] = { 3, 3, 4, 4 };
    VA = vector(A9, A9 + 4);
    VB = vector(B9, B9 + 4);
    test(VA, VB, 8);
    int A10[] = { 1, 2, 3, 4, 1, 2, 3, 4, 1,
                     2, 3, 4, 1, 2, 3, 4 };
    int B10[] = { 1, 1, 1, 1, 2, 2, 2, 2, 3,
                      3, 3, 3, 4, 4, 4, 4 };
    VA = vector(A10, A10 + 16);
    VB = vector(B10, B10 + 16);
    test(VA, VB, 192);
    int A11[] = { 13, 14, 15, 16, 13, 14, 15,
         16, 13, 14, 15, 16, 13, 14, 15, 16 };
    int B11[] = { 13, 13, 13, 13, 14, 14, 14,
         14, 15, 15, 15, 15, 16, 16, 16, 16 };
    VA = vector(A11, A11 + 16);
    VB = vector(B11, B11 + 16);
    test(VA, VB, 192);
    return 0;
}

Output: 

Result: 5
Result: 6
Result: 4
Result: 54
Result: 54
Result: 3
Result: 3
Result: 4
Result: 4
Result: 8
Result: 8
Result: 192
Result: 192

推荐阅读
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • C++语言入门:数组的基本知识和应用领域
    本文介绍了C++语言的基本知识和应用领域,包括C++语言与Python语言的区别、C++语言的结构化特点、关键字和控制语句的使用、运算符的种类和表达式的灵活性、各种数据类型的运算以及指针概念的引入。同时,还探讨了C++语言在代码效率方面的优势和与汇编语言的比较。对于想要学习C++语言的初学者来说,本文提供了一个简洁而全面的入门指南。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • C++中的三角函数计算及其应用
    本文介绍了C++中的三角函数的计算方法和应用,包括计算余弦、正弦、正切值以及反三角函数求对应的弧度制角度的示例代码。代码中使用了C++的数学库和命名空间,通过赋值和输出语句实现了三角函数的计算和结果显示。通过学习本文,读者可以了解到C++中三角函数的基本用法和应用场景。 ... [详细]
  • 集合的遍历方式及其局限性
    本文介绍了Java中集合的遍历方式,重点介绍了for-each语句的用法和优势。同时指出了for-each语句无法引用数组或集合的索引的局限性。通过示例代码展示了for-each语句的使用方法,并提供了改写为for语句版本的方法。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • 本文介绍了一道经典的状态压缩题目——关灯问题2,并提供了解决该问题的算法思路。通过使用二进制表示灯的状态,并枚举所有可能的状态,可以求解出最少按按钮的次数,从而将所有灯关掉。本文还对状压和位运算进行了解释,并指出了该方法的适用性和局限性。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
author-avatar
羊爱恋上狼
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有