【BZOJ1061】[Noi2008]志愿者招募
Description
申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这并不是他的特长!于是布布找到了你,希望你帮他设计一种最优的招募方案。
Input
第一行包含两个整数N, M,表示完成项目的天数和可以招募的志愿者的种类。 接下来的一行中包含N 个非负整数,表示每天至少需要的志愿者人数。 接下来的M 行中每行包含三个整数Si, Ti, Ci,含义如上文所述。为了方便起见,我们可以认为每类志愿者的数量都是无限多的。
Output
仅包含一个整数,表示你所设计的最优方案的总费用。
Sample Input
3 3
2 3 4
1 2 2
2 3 5
3 3 2
2 3 4
1 2 2
2 3 5
3 3 2
Sample Output
14
HINT
1 ≤ N ≤ 1000,1 ≤ M ≤ 10000,题目中其他所涉及的数据均 不超过2^31-1。
题解:先%一发吴大爷http://wenku.baidu.com/view/ce5784754a7302768f99391d
本题给出的条件正好是标准形的,所以可以直接敲板子。不过本题求的是最小值,我们可以转化成对偶问题来求(感觉就是把单纯形表转置了一下~)。
另外在candy的博客上学了全幺模矩阵,感觉十分有用
bz1061:
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> using namespace std; const int maxn=1010; const int maxm=10010; const double eps=1e-5; const double inf=1e12; double A[maxm][maxn]; int p[maxn]; int n,m; //0?->C ?0->B 00->ans void pivot(int l,int e) { double t=A[l][e];A[l][e]=1; int i,j; for(j=0;j<=n;j++) A[l][j]/=t; for(p[0]=j=0;j<=n;j++) if(fabs(A[l][j])>eps) p[++p[0]]=j; for(i=0;i<=m;i++) if(i!=l&&fabs(A[i][e])>eps) { t=A[i][e],A[i][e]=0; for(j=1;j<=p[0];j++) A[i][p[j]]-=t*A[l][p[j]]; } } void simplex() { while(1) { double mn=inf; int i,j,l=0,e=0; for(j=1;j<=n;j++) if(A[0][j]>eps) { e=j; break; } if(!e) return ; for(i=1;i<=m;i++) if(A[i][e]>eps&&A[i][0]/A[i][e]<mn) mn=A[i][0]/A[i][e],l=i; if(!l) return ; pivot(l,e); } } int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); return ret*f; } int main() { n=rd(),m=rd(); int i,j,l,r; for(i=1;i<=n;i++) A[0][i]=rd(); for(i=1;i<=m;i++) { l=rd(),r=rd(),A[i][0]=rd(); for(j=l;j<=r;j++) A[i][j]=1; } simplex(); printf("%d",int(-A[0][0]+0.5)); return 0; }
bz3265:
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> using namespace std; const double eps=1e-7; const double inf=1e12; double A[10010][1010]; int p[1010]; int n,m; void pivot(int l,int e) { double t=A[l][e];A[l][e]=1; int i,j; for(j=0;j<=n;j++) A[l][j]/=t; for(p[0]=j=0;j<=n;j++) if(fabs(A[l][j])>eps) p[++p[0]]=j; for(i=0;i<=m;i++) if(i!=l&&fabs(A[i][e])>eps) { t=A[i][e],A[i][e]=0; for(j=1;j<=p[0];j++) A[i][p[j]]-=t*A[l][p[j]]; } } void simplex() { while(1) { double mn=inf; int i,j,l=0,e=0; for(j=1;j<=n;j++) if(A[0][j]>eps) { e=j; break; } if(!e) return ; for(i=1;i<=m;i++) if(A[i][e]>eps&&A[i][0]/A[i][e]<mn) mn=A[i][0]/A[i][e],l=i; if(!l) return ; pivot(l,e); } } int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); return ret*f; } int main() { n=rd(),m=rd(); int i,j,a,l,r; for(i=1;i<=n;i++) A[0][i]=rd(); for(i=1;i<=m;i++) { a=rd(); while(a--) { l=rd(),r=rd(); for(j=l;j<=r;j++) A[i][j]=1; } A[i][0]=rd(); } simplex(); printf("%d",int(-A[0][0]+0.5)); return 0; }