【传送门:BZOJ2426】
简要题意:
有一个旧发电厂,每年需耗费h[0]的租费,有m个矿场,每个矿场每年产出a[i]吨煤,而每个矿场运煤到旧发电厂的费用为每吨c[0][j],现在要新建一个新发电厂,这个新发电厂有n个预备选址,n个预备选址的每年的租费为h[i],每个矿场运煤到每个预备选址的费用为每吨c[i][j]。
已知旧发电厂需要b吨煤(不多不少,就b吨),而其他煤都运去新发电厂,请在n个预备选址中选出一个作为新发电厂,使得每年的总费用最少
题解:
贪心(我比较正直,所以贪心题不太能一眼秒)
一个一个预备选址来处理
先把所有煤运到当前预备选址,然后记录每个煤矿运到旧发电厂和预备选址的费用差,然后排序一遍
然后从小到大填充b,只要累加费用差*最大能运的煤数,就能够消除预备选址的影响,得到旧发电厂的费用
最后记录最小值即可
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; int c0[51000],c1[51000]; int h[51]; struct node { int d,id; }v[51000]; bool cmp(node n1,node n2) { return n1.d<n2.d; } int a[51000]; int main() { int m,b,n; scanf("%d%d%d%d",&m,&b,&h[0],&n); for(int i=1;i<=m;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&h[i]); for(int i=1;i<=m;i++) scanf("%d",&c0[i]); int ans=999999999,t,sum; for(int T=1;T<=n;T++) { sum=0; for(int i=1;i<=m;i++) { scanf("%d",&c1[i]); sum+=c1[i]*a[i]; v[i].d=c0[i]-c1[i]; v[i].id=i; } sum+=h[T]; sort(v+1,v+m+1,cmp); int bb=b; for(int i=1;i<=m;i++) { if(bb==0) break; int tt=min(bb,a[v[i].id]); sum+=v[i].d*tt; bb-=tt; } if(ans>sum) { ans=sum; t=T; } } printf("%d\n%d\n",t,ans+h[0]); return 0; }