简体   繁体   English

如何找到最低成本?

[英]How to find the minimum cost?

I'm trying to solve a problem which consists of finding minimum cost.The problem can be stated as: Given n buildings and for each building its height and cost is given.Now task is to find minimum cost so that all the buildings become equal to same height.Each building can be considered as a vertical pile of bricks where each brick can be added or removed with the cost associated with that building. 我试图解决一个问题,包括找到最低成本。问题可以说是:给定n个建筑物和每个建筑物的高度和成本。现在的任务是找到最低成本,使所有建筑物变得平等每个建筑都可以被认为是一堆垂直的砖块,每块砖都可以加入或移除,并与建筑物相关。

For example: Say there are n=3 buildings with heights of 1,2,3 and cost 10,100,1000 respectively. 例如:假设有n = 3栋建筑,其高度分别为1,2,3和10,100,1000。

Here, minimum cost will be equal to 120. 在这里,最低成本将等于120。

Here is the link to the problem: 以下是问题的链接:

http://www.spoj.pl/problems/KOPC12A/ http://www.spoj.pl/problems/KOPC12A/

An obvious answer will be to find the cost associated with each of the heights for all the buildings and then give as output the minimum cost from them.This is O(n^2). 一个明显的答案是找到与所有建筑物的每个高度相关的成本,然后从它们作为输出给出最小成本。这是O(n ^ 2)。

In search for a better solution I tried finding the height with minimum value of ratio of height/cost.Then all the buildings must be equal to this height and calculate the cost and give as output.But this is giving me wrong answer. 为了寻找更好的解决方案,我尝试用高度/成本比率的最小值来找到高度。然后所有建筑物必须等于这个高度并计算成本并给出输出。但这给了我错误的答案。 Here is my implementation: 这是我的实现:

Based on the below answers I have updated my code using weighted average but still not working.It's giving me wrong answer. 根据以下答案,我使用加权平均值更新了我的代码,但仍然没有工作。它给了我错误的答案。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>

using namespace std;

long long fun(int h[],int c[],int optimal_h,int n){
    long long res=0;
    for(int i=0;i<n;i++){
        res += (abs(h[i]-optimal_h))*c[i];
    }   
    return res;
}

int main()
{
    int t;
    cin>>t;
    for(int w=0;w<t;w++){
        int n;
        cin>>n;
        int h[n];
        int c[n];
        int a[n];
        int hh[n];
        for(int i=0;i<n;i++){
            cin>>h[i];
            hh[i]=h[i]; 
        }
        sort(hh,hh+n);
        for(int i=0;i<n;i++)
            cin>>c[i];

        long long w_sum=0;  
        long long cost=0;

        for(int i=0;i<n;i++){
            w_sum += h[i]*c[i];
            cost += c[i];   
        }

        int optimal_h;
        if(cost!=0){
            optimal_h=(int)((double)w_sum/cost + 0.5);
            if(!binary_search(hh,hh+n,optimal_h)){
                int idx=lower_bound(hh,hh+n,optimal_h)-hh;
                int optimal_h1=hh[idx];
                int optimal_h2=hh[idx-1];
                long long res1=fun(h,c,optimal_h1,n);
                long long res2=fun(h,c,optimal_h2,n);
                if(res1<res2)
                    cout<<res1<<"\n";   
                else
                    cout<<res2<<"\n";
            }
            else{
                long long res=fun(h,c,optimal_h,n);
                cout<<res<<"\n";
            }

        }
        else
            cout<<"0\n";
    }

    return 0;
}

Any idea how to solve this ? 不知道怎么解决这个问题?

Try thinking about heights as values and costs as certainty,significance. 尝试将高度视为价值和成本作为确定性和重要性。

Simple weighted average should do the trick here: 简单的加权平均值应该在这里诀窍:

costsum=0;
weightedsum=0;
for(int i=0; i<n; ++i)
{
   costsum += c[i];
   weightedsum += h[i]*c[i];
}

optimalheight = round(double(weightedsum)/costsum);

Then count the cost knowing the optimal height: 然后计算知道最佳高度的成本:

cost=0;
for(int i=0; i<n; ++i)
   cost += c[i] * abs(h[i] - optimalheight);

I recently encountered a similar question, the minor difference is that in my question, it's only possible to add floors to a building, you cannot remove it. 我最近遇到了一个类似的问题,不同的是,在我的问题中,它只能添加到建筑物的楼层,你不能删除它。 But the idea should be similar. 但这个想法应该是相似的。 Feel free to drop me any comments or questions. 请随时给我任何评论或问题。

I think one good way to approach this question is: Sort the input first, this could usually be done with language built-in API calls, in Java, I used Arrays.sort(). 我认为解决这个问题的一个好方法是:首先对输入进行排序,通常可以使用语言内置的API调用来完成,在Java中,我使用了Arrays.sort()。 This is usually nLog(n) time complexity. 这通常是nLog(n)时间复杂度。 After sorting, we can maintain a window of size m, inside the window, we could compute the minimum cost for each window, while we shift the window from the beginning to the end, we compute and update a global minimum cost. 排序后,我们可以在窗口内维护一个大小为m的窗口,我们可以计算每个窗口的最低成本,同时我们将窗口从开始移动到结束,我们计算并更新全局最小成本。 Here's the implementation: 这是实施:

    static long minFloors(long[] buildings, int m) {
        //sort buildings
        Arrays.sort(buildings);
        //maintain a window of size m, compute the minCost of each window, update minCost along the way as the final result
        long minCost = Long.MAX_VALUE;
        for(int i = 0; i <= buildings.length-m; i++){
            long heightToMatch = buildings[i+m-1];
            if(heightToMatch == buildings[i]) return 0;//if the last building's height equals the first one, that means the whole window if of the same size, we can directly return 0
            long thisCost = 0; 
            for(int j = i+m-1; j >= i; j--){
                thisCost += heightToMatch - buildings[j];
            }
            minCost = Math.min(minCost, thisCost);
        }
        return minCost;
    }

Also I shared my solution here: Space Rock question 我也在这里分享了我的解决方案: Space Rock问题

Here is a solution that requires the building heights be sorted (I'm going to assume from shortest to tallest). 这是一个解决方案,需要对建筑物高度进行排序(我将假设从最短到最高)。 If the data is already sorted then this should run in O(N) time. 如果数据已经排序,那么这应该在O(N)时间内运行。

Let k be the height of all the buildings, so we want to find the optimal k. 设k为所有建筑物的高度,因此我们希望找到最佳k。 The cost of adjusting all these buildings is given by: 调整所有这些建筑物的成本由下式给出:

    M = Sum(|k-hj|cj, j from 0 to N).

Now because they are sorted we can find an index i such that for all j <= i, hj <= k and for all j > i, hj > k. 现在因为它们被排序,我们可以找到索引i,使得对于所有j <= i,hj <= k并且对于所有j> i,hj> k。 This means we can rewrite our cost equation to be: 这意味着我们可以将我们的成本等式重写为:

    M = Sum((k-hj)cj, j = 0 to i) + Sum((hj-k)cj, j = i+1 to N).

Now we will iterate through the k values between the shortest and the tallest building until we find the one with the lowest cost (we will see further down that we don't have to check every single one) Calculating the cost at every iteration is N operations, so we will find a recursive definition of our cost function instead: 现在我们将迭代最短和最高建筑之间的k值,直到我们找到成本最低的那个(我们将进一步看到我们不必检查每一个)计算每次迭代的成本是N操作,所以我们将找到我们的成本函数的递归定义:

    M(k+1) = Sum((k+1-hj)cj, j = 0 to p) + Sum((hj-k-1)cj, j = p+1 to N).

We can move the '1' terms out of the sums to get: 我们可以将“1”项从总和中移出来得到:

    M(k+1) = Sum((k-hj)cj, j = 0 to p) + Sum((hj-k)cj, j = p+1 to N) + Sum(cj, j = 0 to p) - Sum(cj, j = p+1 to N).

Now p is the new i, and there are 2 possible cases: p = i or p = i+1. 现在p是新的i,有两种可能的情况:p = i或p = i + 1。 if p = i: 如果p = i:

    M(k+1) = M(k) + Sum(cj, j = 0 to p) - Sum(cj, j = p+1 to N)

and if p = i+1 如果p = i + 1

    M(k+1) = M(k) + Sum(cj, j = 0 to p) - Sum(cj, j = p+1 to N) + 2(k+1 - h(i+1))c(i+1).

In the case where p=i we can actually find M(k+m) directly from M(k) because at each iteration we are only adding a constant term (constant in terms of k that is) so if p = i: 在p = i的情况下,我们实际上可以直接从M(k)找到M(k + m),因为在每次迭代时我们只添加一个常数项(就k而言是常数),所以如果p = i:

    M(k+m) = M(k) + m(Sum(cj, j = 0 to p) - Sum(cj, j = p+1 to N)).

This means that our function forms a straight line between iterations where i is constant. 这意味着我们的函数在迭代之间形成一条直线,其中i是常数。 Since we are interested in when our function goes from decreasing to increasing this cannot happen between in the middle of all these iterations. 由于我们对函数从递减到递增感兴趣,因此在所有这些迭代的中间不会发生这种情况。 It can only happen when i increments (p = i+1) or the first step after (since the line is different from the line leading up to it). 它只能在i递增(p = i + 1)或之后的第一步(因为该行与导致它的行不同)时发生。 From what's here so far the algorithm would go something like: 到目前为止,算法将会是这样的:

  1. Sort the heights if necessary (O(NlogN)) 必要时对高度排序(O(NlogN))
  2. Initialize your 4 sums (the two sums in M(k) and the two additional sums introduced in M(k+1)) (O(N)) 初始化你的4个和(M(k)中的两个和M(k + 1)中引入的两个额外的和)(O(N))
  3. iterate through your heights like this (O(N)) finding the minimum value as you go: 迭代这样的高度(O(N))找到最小值:

    -Increase k to the height of the next tallest building less one (using the M(k+m)) and see if this represents a new minimum - 将k增加到下一个最高建筑物的高度减去一个(使用M(k + m))并查看这是否代表新的最小值

    -Increase k by one changing i values and see if this represents a new minimum - 将k增加1,改变i值,看看这是否代表新的最小值

  4. Print out answer. 打印出答案。

There are some other optimizations possible here that I haven't thought too much about yet. 还有其他一些可能的优化,我还没有想太多。 The obvious one is to not recalculate your sums whenever i changes. 显而易见的是,每当我改变时都不会重新计算你的金额。

I apologize if the math is hard to read, I'm new at StackOverflow and haven't figured out all the formats possible. 如果数学很难读,我很抱歉,我是StackOverflow的新手并且没有想出所有可能的格式。

I don't have any code to support this so I hope this is good enough. 我没有任何代码来支持这一点,所以我希望这已经足够了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM