[haoi2010]工厂选址
某地区有m座矿,其中第i号矿每年产量为ai吨,现有火力发电站一个,每年需用煤b吨,每年运行的固定费用(包括折旧费,不包括煤的运费)为h元,每吨原煤从第i号矿运到原有发电厂的运费为Ci0(i=1,2,…,m;j=1,2,…,n)。
现规划新建一个发电厂,m座煤矿每年开采的原煤将全部供给这两座发电厂。现有n个备选的厂址。若在第j号备选厂址建新厂,每年运行的固定费用为hi元。每吨原煤从第i号矿运到j号备选厂址的运费为Cij(i=1,2,…,m;j=1,2,…,n)。
试问:应把新厂厂址选取在何处?m座煤矿开采的原煤应如何分配给两个发电厂,才能使每年的总费用(发电厂运行费用与原煤费用之和)为最小。
题解:贪心;
这题比较直接,只让求使费用最小,没有收益这一项限制,所以一维的贪心就够了;
主要操作:排序;
提醒:答案可能超出int范围,以及注意数组范围;
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<ctime> #include<algorithm> #include<cstdlib> #include<map> #include<set> #include<vector> #include<queue> #include<cmath> using namespace std; #define FILE "dealing" #define LL long long #define up(i,j,n) for(int i=j;i<=n;i++) #define pii pair<LL,LL> #define piii pair<LL,pair<LL,LL> > template<typename T> inline bool chkmin(T &a,T b){return a>b?a=b,true:false;} template<typename T> inline bool chkmax(T &a,T b){return a<b?a=b,true:false;} namespace IO{ char *fs,*ft,buf[1<<15]; inline char gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;} inline int read(){ LL x=0;int ch=gc();bool f=0; while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();} while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();} return f?-x:x; } }using namespace IO; namespace OI{ const LL maxn(50100),inf(100000000000LL),mod(10000); int M,B,H,N; int a[maxn],h[maxn],c[55][maxn]; struct node{ int id,d; inline bool operator<(const node& b)const{return d<b.d;} }e[maxn]; void slove(){ M=read(),B=read(),H=read(),N=read(); up(i,1,M)a[i]=read(); up(i,1,N)h[i]=read(); up(i,0,N)up(j,1,M)c[i][j]=read();//由j厂运到i位置 LL Min=inf,Id; up(i,1,N){ up(j,1,M)e[j].id=j,e[j].d=c[0][j]-c[i][j]; sort(e+1,e+M+1); LL sum=0,t=0; up(j,1,M){ if(sum<B){ sum+=a[e[j].id]; t+=c[0][e[j].id]*a[e[j].id]; if(sum>B){ t=t-(sum-B)*c[0][e[j].id]+(sum-B)*c[i][e[j].id]; sum=B; } } else t+=c[i][e[j].id]*a[e[j].id]; } t+=H+h[i]; if(t<Min)Min=t,Id=i; } printf("%I64d\n%I64d\n",Id,Min); } } int main(){ freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); using namespace OI; slove(); return 0; }