Java 在给定约束的最小移动中,将数组减少为0

Java 在给定约束的最小移动中,将数组减少为0,java,algorithm,data-structures,dynamic-programming,divide-and-conquer,Java,Algorithm,Data Structures,Dynamic Programming,Divide And Conquer,您将看到一个位于x轴上的城市。它有n座建筑物。第一座建筑位于x=1,高度为h1,第二座建筑位于x=2,高度为h2,依此类推。你是一个拿着剑的巨大怪物,想要摧毁这座城市。你的内心也是一名计算机科学家,所以你的效率是关键,因此你想用最少的移动次数来摧毁这座城市 您可以执行以下两个动作之一: 1。从x=L到x=R进行水平切割,将建筑物的高度从x=L到x=R减少1。 2。在x=P处进行垂直切割,在x=P处完全破坏建筑物,从而使其高度为零。** 注意:对于第一种移动,从L到R范围内的每个城市必须至少有一个

您将看到一个位于x轴上的城市。它有n座建筑物。第一座建筑位于x=1,高度为h1,第二座建筑位于x=2,高度为h2,依此类推。你是一个拿着剑的巨大怪物,想要摧毁这座城市。你的内心也是一名计算机科学家,所以你的效率是关键,因此你想用最少的移动次数来摧毁这座城市

您可以执行以下两个动作之一:

1。从x=L到x=R进行水平切割,将建筑物的高度从x=L到x=R减少1。

2。在x=P处进行垂直切割,在x=P处完全破坏建筑物,从而使其高度为零。**

注意:对于第一种移动,从L到R范围内的每个城市必须至少有一个剩余高度,即不能穿过空白区域。

打印摧毁城市所需的最少移动次数

输入

第一行包含测试用例的数量。 对于每个测试用例,第一行包含建筑物的数量n。 第二行包含n个整数,表示建筑物的高度

输出

对于每个测试用例,在新行上打印摧毁城市的最小移动次数

注释

一,≤ N≤ 1000 0≤ 你好≤ 一千

样本输入0

二,

五,

2 2 3 3

五,

10210210

样本输出0

三,

五,

我想不出解决这个问题的方法。 我的代码不适用于以下输入: 1 1 1 2 4 5 7 7 8 9** 在我的代码中,我减少了所有元素的最小值。然后找出零之间的子阵,然后将子阵长度(j-i)与最小值进行比较。如果长度小于,那么我们需要跟随移动2,否则移动1。 我的代码:

import java.util.ArrayList;
导入java.util.array;
导入java.util.List;
导入java.util.stream.collector;
导入java.util.stream.IntStream;
导入java.util.Scanner;
公共班机{
静态int findmin(int arr[],int i,int j){
int min=整数最大值;
对于(int k=i;karr[k]){
最小值=arr[k];
}
}
返回最小值;
}
静态空差最小值(int arr[],int i,int j,int min){
//如果子阵的长度和最小值相等,我们将分别销毁
if(j-i输入[i]){
min=输入[i];
}
如果(输入[i]==0){
零++;
}
}
//从数组中减去最小元素
整数计数=0;
如果(零=0){
计数+=分钟;
减法最小值(输入,0,n,最小值);
}否则{
计数+=分钟;
减法最小值(输入,0,n,最小值);
}
//在0之间遍历数组和FindSubArray
//1) 如果一个元素被0包围,它将立即被单独销毁

//2)同样,如果子阵列的长度这里一个可能的提示是,将建筑减少到零会分隔部分,这意味着分而治之

f(A,l,r)
表示
A
段在
[l,r]
处索引的最佳移动次数。然后:

f(A, l, r):
  min(
    # Reduce the whole section
    # without separating it, using
    # move 1, the horizontal cuts.
    max(A[l..r]),
    
    # Divide and conquer
    1 + f(A, l, k-1) + f(A, k+1, r)
  )
  for all l ≤ k ≤ r
除了我们不需要尝试所有
k
s外,只需指向
max(A)
的一个。不删除
max(A)
意味着我们需要执行
max(A)
移动,或者我们以后必须删除它

JavaScript代码:

函数findMax(A、l、r){
设idx=l;
for(设i=l;ia[idx])
idx=i;
返回idx;
}
函数f(A,l=0,r=A.length-1,memo={}){
如果(l>r)
返回0;
如果(l==r)
返回1;
常量键=字符串([l,r]);
if(备注hasOwnProperty(键))
返回备忘录[键];
常数k=findMax(A,l,r);
const best=Math.min(A[k],1+f(A,l,k-1,memo)+f(A,k+1,r,memo));
返回备忘录[键]=最佳;
}
变量As=[
[2, 2, 2, 3, 3],
[10, 2, 10, 2, 10],
[1, 1, 1, 2, 4, 5, 7, 7, 8, 9]
];
例如

console.log(f(A));
您遇到的问题不在代码中,而在算法中。如果段的大小足够小,则必须有效地执行move 2。但是,此条件不是必不可少的

实际上,简单的递归方法可以解决这个问题。在给定的段[k,l]中,减去最小值后,您只需执行以下操作:

n_moves  = min (n, vmin + min_moves(x, k, l));
在下面,一个函数检测零的位置,并将对应于每个段的移动相加 为每个段调用另一个函数,内部没有零

下面的代码是C++的,但是它相当简单,应该很容易翻译成另一种语言。 输出:

1 2 7  : 3
2 2 2 3 3  : 3
10 2 10 2 10  : 5
1 1 1 2 4 5 7 7 8 9  : 8
提供此代码是为了完整性。重要的是算法本身

#include    <iostream>
#include    <vector>
#include    <algorithm>

std::vector<int> get_zeros (const std::vector<int> &x, int k, int l) {
    std::vector<int> zeros;
    for (int i = k; i <= l; ++i) {
        if (x[i] == 0) zeros.push_back(i);
    }
    return zeros;
}

int min_moves (std::vector<int> &x, int k, int l);

//  This function is called after detection the position of the zeros -> no zero inside
int min_moves_no_zero (std::vector<int> &x, int k, int l) {
    int n = l-k+1;
    if (n == 0) return 0;
    if (n == 1) return 1;
    int vmin = 10000;
    for (int i = k; i <= l; ++i) {
        if (x[i] < vmin) vmin = x[i];
    }
    for (int i = k; i <= l; ++i) {
        x[i] -= vmin;
    }
    
    int nm = std::min (n, vmin + min_moves(x, k, l));
    
    return nm;
}
    
//  This function detects positions of the zeros and sum the moves corresponding to each segment
int min_moves (std::vector<int> &x, int k, int l) {
    auto zeros = get_zeros (x, k, l);
    if (zeros.size() == 0) return min_moves_no_zero (x, k, l);
    int start = k;
    int total = 0;
    for (int z = 0; z < zeros.size(); ++z) {
        int end = zeros[z] - 1;
        if (start != zeros[z]) {
            total += min_moves_no_zero (x, start, end);
        }
        start = end + 2;
    }
    if (start <= l) {
        total += min_moves_no_zero (x, start, l);
    }

    return total;
}

void print (const std::vector<int> &x) {
    for (auto k: x) {
        std::cout << k << " ";
    }
}

int main() {
    std::vector<std::vector<int>> input {
        {1, 2, 7}, 
        {2, 2, 2, 3, 3},
        {10, 2, 10, 2, 10},
        {1, 1, 1, 2, 4, 5, 7, 7, 8, 9}
    };
    
    for (auto& arr: input) {
        auto save = arr;
        int moves = min_moves (arr, 0, arr.size()-1);
        print (save);
        std::cout << " : " << moves << "\n";
    }
}
#包括
#包括
#包括
std::vector get_zero(const std::vector&x,int k,int l){
std::向量零;
对于(int i=k;i内部无零
整数最小值移动零(标准::向量&x,整数k,整数l){
int n=l-k+1;
如果(n==0)返回0;
如果(n==1)返回1;
int-vmin=10000;

对于(int i=k;i这与java或python有什么关系?:)嘿!请发布你的代码。我发布了我的代码。你提到你的代码不适用于此输入。输出是什么?预期输出是什么?我的输出是9。预期输出是8。请注意,OP要求的是
java
,而不是
Javascript
(编辑后)。
#include    <iostream>
#include    <vector>
#include    <algorithm>

std::vector<int> get_zeros (const std::vector<int> &x, int k, int l) {
    std::vector<int> zeros;
    for (int i = k; i <= l; ++i) {
        if (x[i] == 0) zeros.push_back(i);
    }
    return zeros;
}

int min_moves (std::vector<int> &x, int k, int l);

//  This function is called after detection the position of the zeros -> no zero inside
int min_moves_no_zero (std::vector<int> &x, int k, int l) {
    int n = l-k+1;
    if (n == 0) return 0;
    if (n == 1) return 1;
    int vmin = 10000;
    for (int i = k; i <= l; ++i) {
        if (x[i] < vmin) vmin = x[i];
    }
    for (int i = k; i <= l; ++i) {
        x[i] -= vmin;
    }
    
    int nm = std::min (n, vmin + min_moves(x, k, l));
    
    return nm;
}
    
//  This function detects positions of the zeros and sum the moves corresponding to each segment
int min_moves (std::vector<int> &x, int k, int l) {
    auto zeros = get_zeros (x, k, l);
    if (zeros.size() == 0) return min_moves_no_zero (x, k, l);
    int start = k;
    int total = 0;
    for (int z = 0; z < zeros.size(); ++z) {
        int end = zeros[z] - 1;
        if (start != zeros[z]) {
            total += min_moves_no_zero (x, start, end);
        }
        start = end + 2;
    }
    if (start <= l) {
        total += min_moves_no_zero (x, start, l);
    }

    return total;
}

void print (const std::vector<int> &x) {
    for (auto k: x) {
        std::cout << k << " ";
    }
}

int main() {
    std::vector<std::vector<int>> input {
        {1, 2, 7}, 
        {2, 2, 2, 3, 3},
        {10, 2, 10, 2, 10},
        {1, 1, 1, 2, 4, 5, 7, 7, 8, 9}
    };
    
    for (auto& arr: input) {
        auto save = arr;
        int moves = min_moves (arr, 0, arr.size()-1);
        print (save);
        std::cout << " : " << moves << "\n";
    }
}