推荐一篇论文:http://wenku.baidu.com/view/ce5784754a7302768f99391d
我们设xi为第i个志愿者的招募次数,以样例为例,则不难列出如下的线性规划方程:
min{2x1+5x2+2x3}
x1+0+0>=2
x1+x2+0>=3
0+x2+x3>=4
那么,根据论文,这个方程等价于:
max{2x1+3x2+4x3}
x1+x2+0<=2
0+x2+x3<=5
0+0+x3<=2
我们发现,这是一个线性规划方程的基本形式,基本解为{0,0,0}
然后套模板就可以了。
#include <cstdio> const int N=1005,M=10005; int n,m,x,y,p,id; double ans,c[N],b[M],a[M][N]; void pvt(int id,int p) { a[id][p]=1/a[id][p],b[id]*=a[id][p]; for(int i=1;i<=n;i++) if(i^p) a[id][i]*=a[id][p]; for(int i=1;i<=m;i++) if((i^id)&&a[i][p]) { for(int j=1;j<=n;j++) if(j^p) a[i][j]-=a[i][p]*a[id][j]; b[i]-=a[i][p]*b[id],a[i][p]*=-a[id][p]; } for(int i=1;i<=n;i++) if(i^p) c[i]-=c[p]*a[id][i]; ans+=c[p]*b[id],c[p]*=-a[id][p]; } double sol() { while(1) { for(p=1;p<=n;p++) if(c[p]>0) break; if(p==n+1) return ans; double fz=0x3f3f3f3f; for(int i=1;i<=m;i++) if(a[i][p]>0&&b[i]/a[i][p]<fz) fz=b[i]/a[i][p],id=i; if(fz==0x3f3f3f3f) return fz; pvt(id,p); } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lf",&c[i]); for(int i=1;i<=m;i++) { scanf("%d%d%lf",&x,&y,&b[i]); for(int j=x;j<=y;j++) a[i][j]=1; } printf("%.0f",sol()); return 0; }