有 \(m \leq 5\times 10^4\) 座煤矿,产量分别为 \(a_i \leq 500\),火力发电厂每年需要用 \(b \leq 10^4\) 单位煤,每年运行的固定成本为 \(h \leq 100\),煤从 \(i\) 运送到发电厂的单价为 \(C_{i,0} \leq 50\)。现在计划新建一个发电厂,且所有煤矿开采的煤都供给这两个发电厂。有 \(n \leq 50\) 个备选厂址,第 \(j\) 个的固定运行费用是 \(h_j\leq 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;
}