当前位置: 首页 > 知识库问答 >
问题:

均衡数字列表的最小移动次数

邹弘
2023-03-14

我们有一个 n 个正整数的数组。可接受的做法是将所有元素增加 1 或 2 或 5,但一个元素除外。我们需要找出最小操作数,以使所有数组元素的数量相等。

经过搜索,我找到了一种方法:

  1. 找出非最小元素与最小元素之间的所有差异
  2. 通过使用硬币找零方法,找到为所有差异找零所需的最小硬币数量
  3. 返回所有这些最小硬币数量的总和

但是这种方法对于此测试用例失败:

数组:< code>1,5,5

最小操作数:3 (1,5,5)

按照上面的方法,我得到了4个。

有人能建议正确的方法吗?

这是我的源代码

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <climits>
using namespace std;

int input[10000];
int input1[10000];
int dp[4][1001];
int parent[4][1001];
int coins[4]={0,1,2,5};
int operation=0;
int main() {
    int t,n,i,j,count,sum,diff,prevdiff,min;
    for(i=1;i<1001;i++)
    {
        dp[0][i]=INT_MAX;
        parent[0][i]=INT_MAX;
    }
    for(i=0;i<4;i++)
    {
        dp[i][0]=0;
        parent[i][0]=-1;
    }
    for(i=1;i<1001;i++){
        for(j=1;j<4;j++){
            dp[j][i]=dp[j-1][i];
            parent[j][i]=parent[j-1][i];
            if(i>=coins[j]&&dp[3][i-coins[j]]<INT_MAX){

                if(dp[3][i-coins[j]]+1<dp[j][i]){
                    dp[j][i]=dp[3][i-coins[j]]+1;
                    parent[j][i]=j;
                }
            }
        }
    }
    cin>>t;
    while(t>0){
        cin>>n;
        min=INT_MAX;
        for(i=0;i<n;i++)
        {
            cin>>input[i];
            if(input[i]<min){
                min=input[i];
            }
            //input1[i]=input[i];
        }

        //sort(input,input+n);

        count=0;
        sum=0;

        for(i=0;i<n;i++){
            count=count+dp[3][input[i]-min];
        }

        cout<<count<<endl;
        t--;
    }
    /*
    for(i=1;i<1001;i++){
        if(dp[3][i]!=minCoins(i))
            cout<<dp[3][i]<<" "<<minCoins(i)<<endl;
    }
    */
    return 0;
}

共有2个答案

养焱
2023-03-14

将除一个数以外的所有数增加1、2或5等于将该数减少1、2和5。因此,这个问题可以转化为另一个问题,其中-

我们希望通过仅使用1次运算来使所有数字相等,即将特定数字减少1,2或5。

为了解决这个问题,我们可以在数组中找到最小的数字。所有数字的最终值将是[min(Array)-4, min(Array)]我们可以遍历所有5个值,对于每个值,我们可以找到使所有元素达到所选值的最小移动次数。最后取我们在每个测试用例中得到的所有5个答案中的最小值。这将是结果。这是我的C代码-

#include<bits/stdc++.h>
using namespace std;

#define int long long int

signed main(){
    int t;
    cin>>t;
    while(t--){
        int n, res = INT_MAX, mini = INT_MAX, ans, temp;
        cin>>n;
        int A[n];
        for(int i=0;i<n;i++){
            cin>>A[i];
            mini = min(mini, A[i]);
        }
        for(int i=mini-4;i<=mini;i++){
            ans = 0;
            for(int j=0;j<n;j++){
                temp = A[j]-i;
                temp = temp/5+(temp%5)/2+(temp%5)%2;
                ans += temp;
            }
            res = min(ans, res);
        }
        cout<<res<<"\n";
    }

    return 0;
}
王兴庆
2023-03-14

您发现的方法不适用于由1、2和5组成的元素集。正如您所说,对于1、5、5,该方法会导致4次操作(对于“硬币找零”),例如:

<代码> 1,5,5 -

出于均衡所有元素的目的,将除一个元素之外的所有元素增加1、2或5,本质上与将一个元素减少相应的值相同(见此答案)。如果你这样看待你的问题,那么它等于这个问题。

对后一个问题的回答解释说,仅仅考虑最小要素和非最小要素之间的差异是不够的。您还必须考虑所有元素与最小元素 - 1 和最小元素 - 2 的差异。例如,对于 1、5、5,这将导致以下操作:

<代码> 1,5,5 -

<代码> 1,5,5 -

如您所见,对于您的示例,考虑所有元素和最小元素之间的差异 - 1 给出了均衡所有元素所需的最小操作数,即 3。

您应该调整您的代码,使其反映这种方法。

 类似资料:
  • 给定n个正元素(包括0)的数组。我们只允许执行一个转换,即增加列表中除一个元素外的每个元素。均衡此列表所需的最小转换次数是多少? 例如,< code>n = 3,数组为< code>1,2,3。我们需要3个这样的转换: 并且列表为< code>1,3,2,4,所需的最小变换数是6 解决这个问题的最佳方法是什么?

  • 理论上可以通过只移动未按排序顺序排列的元素来对中的数组进行排序。 最长的递增子序列为: 这些要素的指数如下: 因此,我们需要移动的指数是:

  • 当且仅当“字符串中的所有不同字符重复相同次数”时,称字符串为良好字符串。 现在,给定一个长度为n的字符串,我们必须在这个字符串中进行的最小更改次数是多少,这样字符串就变得正常了。 注意:我们只允许使用小写英文字母,我们可以将任何字母更改为任何其他字母。 示例:让String为yyxzzxxx 那么这里的答案是2。 说明:一种可能的解决方案YYXYXX。我们已将2“z”更改为2“y”。现在“x”和“

  • 问题内容: 我很难找出例如如何从列表中查找分钟 如何通过定义()函数来查找此列表的最小值和最大值 我不想使用内置功能 问题答案: 如果要手动查找最小值作为函数: Python 3.4引入了该软件包,该软件包提供了其他统计信息:

  • 给出了一个大小为n的数组,其中表示位置处的硬币数量。“移动”包括将一定数量的硬币从位置移动到位置或。重新分配硬币所需的最小移动次数是多少,这样每个位置上正好有一枚硬币?你被保证有相同数量的硬币与有的插槽,以分配他们。 例如,给定输入 输出为 null 解决这个问题的有效方法是什么?

  • Python是否有一个SciPy函数或NumPy函数或模块来计算给定特定窗口的一维数组的运行平均值?