[HAOI2010] 工厂选址

(m leq 5 imes 10^4) 座煤矿,产量分别为 (a_i leq 500),火力发电厂每年需要用 (b leq 10^4) 单位煤,每年运行的固定成本为 (h leq 100),煤从 (i) 运送到发电厂的单价为 (C_{i,0} leq 50)。现在计划新建一个发电厂,且所有煤矿开采的煤都供给这两个发电厂。有 (n leq 50) 个备选厂址,第 (j) 个的固定运行费用是 (h_jleq 100),从煤矿 (i) 到厂址 (j) 的运费单价为 (C_{i,j} leq 50)。求最优的规划方案,包括如何选择新厂厂址和如何将原煤分配给两个工厂。

Solution

考虑到 (n) 很小,直接枚举选哪个新工厂

双代价不好处理,但由于实际 work 的只是它们的差,不妨将所有煤全部运送到新工厂的代价计算出来,然后对于一个运送到旧工厂的,我们只需要将它的代价差值作为代价即可

在计算出这样的相对代价后,我们只需要贪心地选出最小相对代价的 (b) 单位的煤即可

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

const int N = 50005;

struct item {
    int x,y;
    bool operator < (const item &b) {
        return x < b.x;
    }
} d[N];

int n,m,a[N],b,h[N],c[N][55];

int solve(int pos) {
    int ans=0;
    for(int i=1;i<=m;i++) ans+=c[i][pos]*a[i];
    for(int i=1;i<=m;i++) d[i].x=c[i][0]-c[i][pos], d[i].y=a[i];
    sort(d+1,d+m+1);
    int rem=b;
    for(int i=1;i<=m;i++) {
        int tmp=min(rem,d[i].y);
        rem-=tmp;
        ans+=tmp*d[i].x;
    }
    return ans;
}

signed main() {
    cin>>m>>b>>h[0]>>n;
    for(int i=1;i<=m;i++) cin>>a[i];
    for(int i=1;i<=n;i++) cin>>h[i];
    for(int i=0;i<=n;i++) for(int j=1;j<=m;j++) cin>>c[j][i];
    int ans=1e18,x=0;
    for(int i=1;i<=n;i++) {
        int tmp=solve(i)+h[i];
        if(tmp<ans) {
            ans=tmp;
            x=i;
        }
    }
    cout<<x<<endl<<ans+h[0]<<endl;
}

原文地址:https://www.cnblogs.com/mollnn/p/12389861.html