Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何使序列成为具有最少步数的非递减序列?_Algorithm_Sorting_Dynamic Programming - Fatal编程技术网

Algorithm 如何使序列成为具有最少步数的非递减序列?

Algorithm 如何使序列成为具有最少步数的非递减序列?,algorithm,sorting,dynamic-programming,Algorithm,Sorting,Dynamic Programming,以下是 给定一个由N个整数组成的序列。在每个步骤中,允许将任何数字的值增加1或减少1。游戏的目标是使序列以最少的步数不递减 例如,给定 3 2-1 2 11 可以将此序列设置为4个步骤中的非递减序列(减少3乘以1,增加-1乘以3) 序列将变为 2 2 2 2 11 我该如何解决这个问题呢?问题表明,您应该尽量减少更改次数。 假设最后一个数字是-1000000。 如果您按顺序运行序列,您将不得不向最后一个元素添加1000002以获得非递减序列,但解决方案将无法满足使用最小步数的要求。 因此,最好

以下是

给定一个由N个整数组成的序列。在每个步骤中,允许将任何数字的值增加1或减少1。游戏的目标是使序列以最少的步数不递减

例如,给定

3 2-1 2 11

可以将此序列设置为4个步骤中的非递减序列(减少3乘以1,增加-1乘以3)

序列将变为

2 2 2 2 11

我该如何解决这个问题呢?

问题表明,您应该尽量减少更改次数。 假设最后一个数字是-1000000。 如果您按顺序运行序列,您将不得不向最后一个元素添加1000002以获得非递减序列,但解决方案将无法满足使用最小步数的要求。
因此,最好在序列中运行一次,记录元素之间的差异。希望你明白我的意思。(我的书面表达没有自己想象的那么清晰:-)

我已经用C#提供了工作代码。它可以很容易地移植到您选择的语言。时间复杂度约为n2。如果count大于minimumValue,则可以在方法GenerateSequenceForveyIndex()中对其进行优化


使用系统;
使用System.Collections.Generic;
命名空间控制台应用程序2
{
班级计划
{
静态void Main(字符串[]参数)
{
Sequence seq=新序列();
seq.generateSequenceForveyIndex();
Console.ReadLine();
}
}
类序列
{
整数计数;
公共序列()
{
//获取输入的数量
Console.WriteLine(“值的数量?”);
this.count=int.Parse(Console.ReadLine());
Console.WriteLine(“输入值,然后返回/输入”);
GetInputSequence();
}
List inputSequence=新列表();
私有void GetInputSequence()
{
for(int index=0;indexnewValue)minimumValue=newValue;
Console.WriteLine(“移动次数:+newValue”);
Console.WriteLine();
}
Console.WriteLine(“最小移动次数:+minimumValue”);
}
专用整数生成顺序循环索引(整数索引)
{
int numberOfMoves=0;
int[]newOutputSequence=newint[count];
int[]差异顺序=新的int[计数];
this.inputSequence.CopyTo(newOutputSequence);
对于(int ind=0;indindex&&differenceSequence[ind]<0)继续;
numberOfMoves+=Math.Abs(差分顺序[ind]);
newOutputSequence[ind]+=差分序列[ind];
}
显示序列(差异序列,“差异序列:”);
显示序列(newOutputSequence,“新序列:”);
返回移动次数;
}
私有静态void DisplaySequence(int[]newOutputSequence,字符串标题)
{
控制台。写入(标题);
for(int i=0;i

算法说明 每个元素值都可以作为轴心值,这意味着其左侧的值应等于其自身的值,右侧的值应大于或等于其自身的值。 已经说过,最多可以有“n”个唯一的非降序序列。 现在,算法获取每个值(请参见方法GenerateSequenceForveyIndex)并生成新的非降序序列

在GenerateSequenceForCurrentIndex()中,确保索引左侧的值等于数组[index]。我们不必担心小于,因为这将由不同的序列处理(当索引<当前索引时)。确保右侧的值大于或等于当前值。任何差异都被视为附加移动(绝对值)

最后,DisplaySequence()只是显示序列中的值。

\include
#include <stdio.h>
#include <stdlib.h>

int get_destination( int numbers[], int size ) {
    int i,j;
    int destination = 0;
    int swap_done = 0;
    for ( i = 0; i < size - 1; i++) {
        for (j = 0; j < size - 1; j++) {
            if ( numbers[j] > numbers[j + 1]){
                destination = j + 1;
                swap_done = 1;
            }
        }
        if ( swap_done ) {
                break;
        }
    }
    return destination;
}
int main( int argc, char **argv ) {
    #define SIZE 5
    //int numbers[SIZE]= {3, 2, -1, 2, 11};
    //int numbers[SIZE]= {1,2,3,4,5};
    int numbers[SIZE]= {2, 1, 1, 1, 1};
    int answer = 0;
    int dest = get_destination( numbers, SIZE);
    if ( dest ) {
        for ( int i = 0; i < SIZE - 1; i++) {
            answer = answer + abs( abs(numbers[i]) - abs(numbers[dest]));
        }
    }
    printf ( "ANSWER = %d\n", answer );
    return 0;
}
#包括 int get_目的地(整数编号[],整数大小){ int i,j; int destination=0; int swap_done=0; 对于(i=0;i数字[j+1]){ 目的地=j+1; 交换完成=1; } } 如果(交换完成){ 打破 } } 返回目的地; } int main(int argc,字符**argv){ #定义尺寸5 //整数[大小]={3,2,-1,2,11}; //整数[大小]={1,2,3,4,5}; 整数[大小]={2,1,1,1,1}; int-answer=0; int dest=获取目的地(数字、大小); 如果(目的地){ 对于(int i=0;iusing System; using System.Collections.Generic; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { Sequence seq = new Sequence(); seq.GenerateSequenceForEveryIndex(); Console.ReadLine(); } } class Sequence { int count; public Sequence() { // Get Number of inputs Console.WriteLine("Number of values? "); this.count = int.Parse(Console.ReadLine()); Console.WriteLine("Enter input values followed by RETURN/ENTER"); GetInputSequence(); } List<int> inputSequence = new List<int>(); private void GetInputSequence() { for (int index = 0; index < count; index++) inputSequence.Add(int.Parse(Console.ReadLine())); } internal void GenerateSequenceForEveryIndex() { int minimumValue = 0; for (int index = 0; index < count; index++) { // Get output sequence for every index // You can make a decision to get the minimum of the moves int newValue = GenerateSequenceForCurrentIndex(index); if (minimumValue == 0 || minimumValue > newValue) minimumValue = newValue; Console.WriteLine("Number of moves: " + newValue); Console.WriteLine(); } Console.WriteLine("Minimum number of moves: " + minimumValue); } private int GenerateSequenceForCurrentIndex(int index) { int numberOfMoves = 0; int[] newOutputSequence = new int[count]; int[] differenceSequence = new int[count]; this.inputSequence.CopyTo(newOutputSequence); for (int ind = 0; ind < count; ind++) { if (ind == index) continue; differenceSequence[ind] = (ind == 0 ? newOutputSequence[index] : newOutputSequence[ind - 1]) - newOutputSequence[ind]; // If sorted as non-decreasing, continue if (ind > index && differenceSequence[ind] < 0) continue; numberOfMoves += Math.Abs(differenceSequence[ind]); newOutputSequence[ind] += differenceSequence[ind]; } DisplaySequence(differenceSequence, "Diff Sequence: "); DisplaySequence(newOutputSequence, "New Sequence: "); return numberOfMoves; } private static void DisplaySequence(int[] newOutputSequence, string heading) { Console.Write(heading); for (int i = 0; i < newOutputSequence.Length; i++) Console.Write(newOutputSequence[i] + " "); Console.WriteLine(); } } }
#include <stdio.h>
#include <stdlib.h>

int get_destination( int numbers[], int size ) {
    int i,j;
    int destination = 0;
    int swap_done = 0;
    for ( i = 0; i < size - 1; i++) {
        for (j = 0; j < size - 1; j++) {
            if ( numbers[j] > numbers[j + 1]){
                destination = j + 1;
                swap_done = 1;
            }
        }
        if ( swap_done ) {
                break;
        }
    }
    return destination;
}
int main( int argc, char **argv ) {
    #define SIZE 5
    //int numbers[SIZE]= {3, 2, -1, 2, 11};
    //int numbers[SIZE]= {1,2,3,4,5};
    int numbers[SIZE]= {2, 1, 1, 1, 1};
    int answer = 0;
    int dest = get_destination( numbers, SIZE);
    if ( dest ) {
        for ( int i = 0; i < SIZE - 1; i++) {
            answer = answer + abs( abs(numbers[i]) - abs(numbers[dest]));
        }
    }
    printf ( "ANSWER = %d\n", answer );
    return 0;
}
   {2} {-1 2 11} --> {2} {2 2 11}
   {2} {-1 0 1}  --> {2} {2 2 2}
   {3}   {2} --> {2}   {2}
   {2 3} {1} --> {1 1} {1}
{3} {2} {-1 2 11}
adjust left group --> {2 2} {-1 2 11}
adjust left group --> {-1 -1 -1 2 11}
{-1 -1 -1  2 11} (adjust left, adjust left)   --> score 7
{ 2  2  2  2 11} (adjust left, adjust right)  --> score 4 (best)
{-1 -1 -1  2 11} (adjust right, adjust left)  --> score 7
{ 3  3  3  3 11} (adjust right, adjust right) --> score 6
f(1,1)=|a1-b1|
f(1,j)=min{|a1-bj|,f(1,j-1)},  j>1
f(i,1)=|ai-b1|+f(i-1,1),  i>1
f(i,j)=min{f(i,j-1),f(i-1,j)+|ai-bj|},  i>1, j>1