1. 程式人生 > >BZOJ 2426 [HAOI2010]工廠選址 【貪心】

BZOJ 2426 [HAOI2010]工廠選址 【貪心】

如果 tar 兩個 input 加油! ret nbsp can 運行

BZOJ 2426 [HAOI2010]工廠選址

Description

某地區有m座煤礦,其中第i號礦每年產量為ai噸,現有火力發電廠一個,每年需用煤b噸,每年運行的固定費用(包括折舊費,不包括煤的運費)為h元,每噸原煤從第i號礦運到原有發電廠的運費為Ci0(i=1,2,…,m)。

現規劃新建一個發電廠,m座煤礦每年開采的原煤將全部供給這兩座發電廠。現有n個備選的廠址。若在第j號備選廠址建新廠,每年運行的固定費用為hj元。每噸原煤從第i號礦運到j號備選廠址的運費為Cij(i=1,2,…,m;j=1,2,…,n)。

試問:應把新廠廠址選取在何處?m座煤礦開采的原煤應如何分配給兩個發電廠,才能使每年的總費用(發電廠運行費用與原煤運費之和)為最小。

Input

第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

Output

第1行:新廠址編號,如果有多個編號滿足要求,輸出最小的。

第2行:總費用

Sample Input

4 2 7 9
3 1 10 3
6 3 7 1 10 2 7 4 9
1 2 4 3
6 6 8 2
4 10 8 4
10 2 9 2
7 6 6 2
9 3 7 1
2 1 6 9
3 1 10 9
4 2 1 8
2 1 3 4

Sample Output

8
49

HINT

對於所有數據, n<=50, m<=50000, b<=10000

題解:

貪心好題,想了好久。。。

枚舉新工廠,先假設所有的煤全部轉移到新工廠了,然後對於每個煤礦廠,記錄把煤運到新工廠,和把煤運到舊工廠的成本差,從小到大排序,再一直往舊廠裏加加加,一直加到滿 B 為止。

計算總成本,更新答案即可。

代碼如下:

技術分享圖片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=50005;
 4 const int inf=1e9;
 5 int n,m,b,H;
 6 struct node{
 7     int pos,num,cha;
 8 }c3[N];
 9 int c1[N],c2[55][N],a[N],h[55],ans1,ans=inf;
10 inline bool cmp(node a,node b)
11 {
12     return a.cha<b.cha;
13 }
14 inline void doing(int pos)
15 {
16     int cost=h[pos]+H;
17     for (int i=1; i<=m; i++)
18     {
19         cost+=a[i]*c2[pos][i];
20         c3[i].cha=c1[i]-c2[pos][i];
21         c3[i].pos=i;
22     }
23     sort(c3+1,c3+1+m,cmp);
24     int tmp=b;
25     for (int i=1; i<=m; i++)
26       if (tmp)
27       {
28           if (tmp>=a[c3[i].pos])
29           {
30               cost+=a[c3[i].pos]*c3[i].cha;
31               tmp-=a[c3[i].pos];
32         }
33         else cost+=tmp*c3[i].cha,tmp=0;
34       }
35       else break;
36     if (cost < ans)
37     {
38         ans1=pos; ans=cost;
39     }
40 }
41 int main()
42 {
43     scanf("%d%d%d%d",&m,&b,&H,&n);
44     for (int i=1; i<=m; i++)
45       scanf("%d",&a[i]);
46     for (int i=1; i<=n; i++)
47       scanf("%d",&h[i]);
48     for (int i=1; i<=m; i++)
49       scanf("%d",&c1[i]);
50     for (int i=1; i<=n; i++)
51       for (int j=1; j<=m; j++)
52         scanf("%d",&c2[i][j]);
53     for (int i=1; i<=n; i++)
54       doing(i);
55     printf("%d\n%d\n",ans1,ans);
56     return 0;
57 }
View Code

加油加油加油!!!fighting fighting fighting!!!

BZOJ 2426 [HAOI2010]工廠選址 【貪心】