C++ 以最少的移动交换箱子
这是一个节目竞赛(已经结束)中的问题。我正在努力解决这个问题,但找不到一个健康的方法来解决 问题如下: IIIT Allahabad将于10月1日至5日举行一年一度的技术文化节MM12。厨师已经同意为这个节日供应糖果。厨师准备了N盒糖果,编号为1到N(每个数字正好出现一次)。厨师对盒子的摆放非常讲究。他想把盒子按特定的顺序排列,但不幸的是厨师很忙。他让你为他重新安排箱子。给定框的当前顺序,必须按指定顺序重新排列框。但是有一个限制。您只能交换两个相邻的箱子以获得所需的订单。输出,所需的此类相邻交换的最小数量 输入 输入的第一行包含一个整数T,即测试用例数。每个测试用例包含3行,第一行包含一个整数N,框数。接下来的两行各包含N个数字,第一行是框的给定顺序,第二行是所需顺序 输出 对于每个测试用例,输出单个整数“K”,即所需的最小相邻交换数。 限制条件:C++ 以最少的移动交换箱子,c++,c,algorithm,C++,C,Algorithm,这是一个节目竞赛(已经结束)中的问题。我正在努力解决这个问题,但找不到一个健康的方法来解决 问题如下: IIIT Allahabad将于10月1日至5日举行一年一度的技术文化节MM12。厨师已经同意为这个节日供应糖果。厨师准备了N盒糖果,编号为1到N(每个数字正好出现一次)。厨师对盒子的摆放非常讲究。他想把盒子按特定的顺序排列,但不幸的是厨师很忙。他让你为他重新安排箱子。给定框的当前顺序,必须按指定顺序重新排列框。但是有一个限制。您只能交换两个相邻的箱子以获得所需的订单。输出,所需的此类相邻交换
1<=T<=10
1<=N<=10^5
输出:
2
3
6
3
我对这个问题几乎一无所知。有人能解释一下这个问题背后的逻辑吗 我无法从数学上证明这一点,但在4/4的测试用例中,您通过从最左边开始(也可以从最右边开始)并向右移动,将框置于正确的位置,从而获得最小交换。即
3 4 5 2 1 //First get the 4 in the right place
4 3 5 2 1 //Done. Now get the 1 in the right place
4 3 5 1 2
4 3 1 5 2
4 1 3 5 2 //Done. Now the 5
4 1 5 3 2 //Done. Now the 2
4 1 5 2 3 //All done.
所以这个算法看起来会给出任何给定输入的最小值。最坏的情况通常看起来像是反转,需要N*(N-1)/2次交换(见例2)。假设所需的顺序是数字的排序顺序,问题归结为在数组中查找反转的数量 如果
i
和array[i]>array[j]
,则称对(i,j)
为反转。这是因为相邻元素之间的每次(最佳)交换都会将反转次数精确地减少1
。您可以通过一种非常类似于合并排序的分治算法在O(n log n)
中找到反转数。这是一个很好的解释
编辑证明反转数等于最佳互换数:
将
i
设为数组中的任意位置。交换array[i]
和array[i+1]
最多可减少1次反转。因此,所需的互换数量至少等于互换数量。另一方面,如果array
没有排序,我们总是可以找到一对(i,i+1)
,这样array[i]>array[i+1]
(即(i,j)
是一个反转),并通过将array[i]
与array[i+1]
交换,将反转数减少1。因此,反转的数量等于交换的最小数量。将源列表减少为(1,2,…,N)的排列。(通过将目标的倒数应用于源)
然后计算倒数的数目
即
向量源=。。。;
向量目标=。。。;
向量inv(N)
对于(int i=0;i
然后使用标准算法计算perm中的反转数。该问题是一个相当“经典”的竞争编程问题,即在数组中计算反转数。反转定义为一对(i,j),其中i- 使用范围和查询计算已记录的小于当前数字的数字数量李>
- 使用上面的信息找出比当前数字大的数字数量。将其添加到反转计数中。注意不要包括正在考虑的要素。(*)
- 将+1调整为元素值处的Fenwick树
3 4 5 2 1 //First get the 4 in the right place
4 3 5 2 1 //Done. Now get the 1 in the right place
4 3 5 1 2
4 3 1 5 2
4 1 3 5 2 //Done. Now the 5
4 1 5 3 2 //Done. Now the 2
4 1 5 2 3 //All done.
vector<int> source = ...;
vector<int> target = ...;
vector<int> inv(N)
for (int i = 0; i < N; i++)
inv[target[i]] = i;
vector<int> perm(N);
for (int i = 0; i < N; i++)
perm[i] = source[inv[i]];
3 4 5 2 1
4 1 5 2 3
(3 4 5 2 1) to (5 1 3 4 2)
5 1 3 4 2
5 1 3 4 2