这里是问题陈述:
给定一个由N个整数组成的序列。每一步可以将任何数字的值增加1或减少1。游戏的目标是以最少的步骤使序列非递减。
例如,给定
3 2 -1 2 11
我们可以在4步内使此序列成为非递减序列(将3减1并将-1增加3)。
(-1) (0) (+3) (0) (0)
序列将变为:
2 2 2 2 11
我该如何解决这个问题?
这里是问题陈述:
给定一个由N个整数组成的序列。每一步可以将任何数字的值增加1或减少1。游戏的目标是以最少的步骤使序列非递减。
例如,给定
3 2 -1 2 11
我们可以在4步内使此序列成为非递减序列(将3减1并将-1增加3)。
(-1) (0) (+3) (0) (0)
2 2 2 2 11
我提供了 C# 的工作代码,可以轻松地移植到您选择的语言中。时间复杂度约为 n2,在 GenerateSequenceForEveryIndex() 方法中,如果计数超过最小值,则可以进行优化。
using 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();
}
}
}
假设{ai}是初始序列,{bi}是相同的序列,但其中所有元素都是不同的,并且按从小到大的顺序排序。令f(i,j)为获得前i个元素非递减且第i个元素最多为bj的序列所需的最小移动次数。在这种情况下,问题的答案将等于f(n,k),其中n是{ai}的长度,k是{bi}的长度。我们将使用以下递推公式计算f(i,j):
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
#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;
}
如果你看一下冒泡排序,第一次外层循环就把元素放在正确的位置上了,我正试图使用这个概念。一旦你找到了第一次交换的位置,就用它作为参考,并根据那个元素调整序列中的所有元素。
好的,问题陈述了你应该努力实现最小数量的更改。 假设最后一个数字是-1000000。 如果您按顺序运行序列,则最终必须将1000002添加到最后一个元素以获得非递减序列,但解决方案将无法满足使用最少步骤的要求。 因此,通过运行一次序列并记录元素之间的差异可能是个好主意。希望你能理解我的意思。(我写作不够清晰,但我自己的想法很清楚 :-))
{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
你需要找到一个符合以下要求的序列:
这是一个带有限制条件的凸整数优化问题,似乎很难找到最佳解。