[HAOI2010]工厂选址
我不要面子的,这题题面我看了好久都没看懂。
首先所有煤矿的产煤都是要运送给两个发电站的,原发电A站须b吨,剩下的所有煤要全部运给新发电站。
考虑枚举新厂址B,计算在每个厂制运煤的最小总代价,取最优解。
现在问题确定厂址B后,如何求最小代价。
因为煤是要全部运出,且从煤矿 i 运至厂 A (X)元,运至厂 B (Y)元,那么可以看作从A->B (Y-X) 元。
可以先使所有煤运到原厂,之后转运到新厂,贪心方法就很明显了,按 (Y-X) 从小到大排序,直至原厂剩 b 吨煤。
// q.c #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; const int M=50000+10,N=50+5; int m,b,h[N],n,a[M],c[M][N]; struct Hole { int sum,delta; bool operator < (const Hole &A) const { return delta<A.delta; } }hole[M]; int solve(int x) { int cost=0,mine=0; for(int i=1;i<=m;i++) { cost+=a[i]*c[i][0]; mine+=a[i]; hole[i].sum=a[i]; hole[i].delta=c[i][x]-c[i][0]; } sort(hole+1,hole+m+1); for(int i=1;i<=m;i++) { if(mine-hole[i].sum>=b) { cost+=hole[i].delta*hole[i].sum; mine-=hole[i].sum; } else { cost+=hole[i].delta*(mine-b); break; } } return cost+h[0]+h[x]; } int main() { freopen("factory1.in","r",stdin); freopen("factory1.out","w",stdout); 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=0;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&c[j][i]); int x=0,y=0x7fffffff,z=0; for(int i=1;i<=n;i++) if((z=solve(i))<y) x=i,y=z; printf("%d %d\n",x,y); return 0; }