【HAOI2010】工厂选址题解
題目描述
某地區(qū)有m座煤礦,其中第i號礦每年產(chǎn)量為ai噸,現(xiàn)有火力發(fā)電廠一個,每年需用煤b噸,每年運行的固定費用(包括折舊費,不包括煤的運費)為h元,每噸原煤從第i號礦運到原有發(fā)電廠的運費為Ci0(i=1,2,…,m)。
現(xiàn)規(guī)劃新建一個發(fā)電廠,m座煤礦每年開采的原煤將全部供給這兩座發(fā)電廠。現(xiàn)有n個備選的廠址。若在第j號備選廠址建新廠,每年運行的固定費用為hj元。每噸原煤從第i號礦運到j(luò)號備選廠址的運費為Cij(i=1,2,…,m;j=1,2,…,n)。
試問:應(yīng)把新廠廠址選取在何處?m座煤礦開采的原煤應(yīng)如何分配給兩個發(fā)電廠,才能使每年的總費用(發(fā)電廠運行費用與原煤運費之和)為最小。
輸入輸出格式
輸入格式:
?
第1行: m b h n
第2行: a1 a2 … am (0<=ai<=500, a1+a2+...+an>=b)
第3行: h1 h2 … hn (0<=hi<=100)
第4行: C10 C20 … Cm0 (0<=Cij<=50)
第5行: C11 C21 … Cm1
… …
第n+4行:C1n C2n … Cmn
?
輸出格式:
?
第1行:新廠址編號,如果有多個編號滿足要求,輸出最小的。
第2行:總費用
說明
對于所有數(shù)據(jù), n<=50, m<=50000, b<=10000
題解
我們看到這道題的數(shù)據(jù),發(fā)現(xiàn)工廠的數(shù)量不會多余50個,所以我們可以考慮枚舉新的工廠的選址。
然后,問題就轉(zhuǎn)化為了兩個工廠如何分配資源使得總花費最小,我們可以利用貪心的思想來做:
如果所有的資源都匯集到新建的廠(now),那么花費就為∑(a[i]*c[i][now]),然后我們要從所有的資源中提取出b的資源使得這個值最小,所以我們可以記錄w[i] = c[i][now] - c[i][0]表示把i的資源移到原工廠每噸會多花多少錢。然后我們在以此排序貪心即可。
這種貪心的思想是利用的一種差值,這個差值的實際含義為:在把所有的關(guān)鍵量都放在一個組中達(dá)到一個定值,然后在從中移取出一部分,而達(dá)到的新的量就是新的花費減去不用的花費在這種情況下我們就可以使用差值來貪心。
程序
#include<bits/stdc++.h>using namespace std; int b, m, n, h; int c[50005][55], cost[55], a[50005]; struct Fact{ int pos, val; }w[50005]; inline bool comp(const Fact & x, const Fact & y) {return x.val > y.val;} int main() { int sumcost = 0x7fffffff, num, tag, ans; scanf("%d%d%d%d", &m, &b, &h, &n); for(int i = 1; i <= m; ++ i) scanf("%d", &a[i]); for(int i = 1; i <= n; ++ i) scanf("%d", &cost[i]); for(int i = 1; i <= m; ++ i) scanf("%d", &c[i][0]); for(int i = 1; i <= n; ++ i) for(int j = 1; j <= m; ++ j) scanf("%d", &c[j][i]); for(int i = 1; i <= n; ++ i) { tag = 0, ans = 0; for(int j = 1; j <= m; ++ j) { w[j].val = c[j][i] - c[j][0]; w[j].pos = j; } sort(w + 1, w + 1 + m, comp); int k = 0; for(;;) { ++ k; if(tag + a[w[k].pos] > b) { ans += c[w[k].pos][0] * (b - tag); ans += c[w[k].pos][i] * (a[w[k].pos] - (b - tag)); break; } tag += a[w[k].pos]; ans += c[w[k].pos][0] * a[w[k].pos]; } for(;k <= m;) ++ k, ans += c[w[k].pos][i] * a[w[k].pos]; ans += h + cost[i]; if(sumcost > ans) { sumcost = ans; num = i; } } printf("%d\n%d\n", num, sumcost); return 0; }?
轉(zhuǎn)載于:https://www.cnblogs.com/2020pengxiyue/p/9459988.html
總結(jié)
以上是生活随笔為你收集整理的【HAOI2010】工厂选址题解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js 简单弹框toast
- 下一篇: fread()