簡體   English   中英

如何找到最低成本?

[英]How to find the minimum cost?

我試圖解決一個問題,包括找到最低成本。問題可以說是:給定n個建築物和每個建築物的高度和成本。現在的任務是找到最低成本,使所有建築物變得平等每個建築都可以被認為是一堆垂直的磚塊,每塊磚都可以加入或移除,並與建築物相關。

例如:假設有n = 3棟建築,其高度分別為1,2,3和10,100,1000。

在這里,最低成本將等於120。

以下是問題的鏈接:

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

一個明顯的答案是找到與所有建築物的每個高度相關的成本,然后從它們作為輸出給出最小成本。這是O(n ^ 2)。

為了尋找更好的解決方案,我嘗試用高度/成本比率的最小值來找到高度。然后所有建築物必須等於這個高度並計算成本並給出輸出。但這給了我錯誤的答案。 這是我的實現:

根據以下答案,我使用加權平均值更新了我的代碼,但仍然沒有工作。它給了我錯誤的答案。

#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;
}

不知道怎么解決這個問題?

嘗試將高度視為價值和成本作為確定性和重要性。

簡單的加權平均值應該在這里訣竅:

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

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

然后計算知道最佳高度的成本:

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

我最近遇到了一個類似的問題,不同的是,在我的問題中,它只能添加到建築物的樓層,你不能刪除它。 但這個想法應該是相似的。 請隨時給我任何評論或問題。

我認為解決這個問題的一個好方法是:首先對輸入進行排序,通常可以使用語言內置的API調用來完成,在Java中,我使用了Arrays.sort()。 這通常是nLog(n)時間復雜度。 排序后,我們可以在窗口內維護一個大小為m的窗口,我們可以計算每個窗口的最低成本,同時我們將窗口從開始移動到結束,我們計算並更新全局最小成本。 這是實施:

    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;
    }

我也在這里分享了我的解決方案: Space Rock問題

這是一個解決方案,需要對建築物高度進行排序(我將假設從最短到最高)。 如果數據已經排序,那么這應該在O(N)時間內運行。

設k為所有建築物的高度,因此我們希望找到最佳k。 調整所有這些建築物的成本由下式給出:

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

現在因為它們被排序,我們可以找到索引i,使得對於所有j <= i,hj <= k並且對於所有j> i,hj> k。 這意味着我們可以將我們的成本等式重寫為:

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

現在我們將迭代最短和最高建築之間的k值,直到我們找到成本最低的那個(我們將進一步看到我們不必檢查每一個)計算每次迭代的成本是N操作,所以我們將找到我們的成本函數的遞歸定義:

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

我們可以將“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).

現在p是新的i,有兩種可能的情況:p = i或p = i + 1。 如果p = i:

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

如果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).

在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)).

這意味着我們的函數在迭代之間形成一條直線,其中i是常數。 由於我們對函數從遞減到遞增感興趣,因此在所有這些迭代的中間不會發生這種情況。 它只能在i遞增(p = i + 1)或之后的第一步(因為該行與導致它的行不同)時發生。 到目前為止,算法將會是這樣的:

  1. 必要時對高度排序(O(NlogN))
  2. 初始化你的4個和(M(k)中的兩個和M(k + 1)中引入的兩個額外的和)(O(N))
  3. 迭代這樣的高度(O(N))找到最小值:

    - 將k增加到下一個最高建築物的高度減去一個(使用M(k + m))並查看這是否代表新的最小值

    - 將k增加1,改變i值,看看這是否代表新的最小值

  4. 打印出答案。

還有其他一些可能的優化,我還沒有想太多。 顯而易見的是,每當我改變時都不會重新計算你的金額。

如果數學很難讀,我很抱歉,我是StackOverflow的新手並且沒有想出所有可能的格式。

我沒有任何代碼來支持這一點,所以我希望這已經足夠了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM