[HAOI2010]工厂选址
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 447 Solved: 308
[Submit][Status][Discuss]
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
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
49
HINT
对于所有数据, n<=50, m<=50000, b<=10000
先假设把所有的煤都放到新工厂,然后对于每一个煤矿场都存一下新老费用的差,然后从小到大排序,,再用原来的费用加上老的费用,
相当于你加上了老的而不用了新的,直到加到老厂有d吨煤为止。枚举一下每一个新厂就行了。
1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #include<algorithm> 6 7 #define N 57 8 #define M 50007 9 #define ll long long 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 15 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 19 int m,b,n; 20 int a[M],h[N<<1],map[N][M]; 21 int ans[N<<1],mmin; 22 struct node 23 { 24 int a,c1,c2,cha,s; 25 }s[M]; 26 27 bool cmp(node n1,node n2) {return n1.cha>n2.cha;} 28 int main() 29 { 30 m=read(),b=read(),h[0]=read(),n=read(); 31 for(int i=1;i<=m;i++) a[i]=read(); 32 for(int i=1;i<=n;i++) h[i]=read(); 33 for(int i=0;i<=n;i++) 34 for(int j=1;j<=m;j++) 35 map[i][j]=read(); 36 mmin=999999999; 37 for(int i=1;i<=n;i++) 38 { 39 for(int j=1;j<=m;j++) {s[j].s=a[j];s[j].a=a[j];s[j].c1=map[0][j];s[j].c2=map[i][j];s[j].cha=map[i][j]-map[0][j];} 40 sort(s+1,s+1+m,cmp);int t=b,sum=0; 41 for(int j=1;j<=m;j++) 42 { 43 if(t!=0) 44 { 45 if(t>=s[j].s) {t-=s[j].s;sum+=s[j].s*s[j].c1;} 46 else {sum+=t*s[j].c1+(s[j].s-t)*s[j].c2;t=0;} 47 }else sum+=s[j].s*s[j].c2; 48 } 49 ans[i]=sum+h[0]+h[i];mmin=min(mmin,ans[i]); 50 } 51 for(int i=1;i<=n;i++) 52 if(ans[i]==mmin) 53 {printf("%d %d ",i,ans[i]);return 0;} 54 }