[ZJOI2013]防守战线
题目描述
战线可以看作一个长度为n 的序列,现在需要在这个序列上建塔来防守敌兵,在序列第i 号位置上建一座塔有Ci 的花费,且一个位置可以建任意多的塔,费用累加计算。有m 个区间[L1, R1], [L2, R2], …, [Lm, Rm],在第i 个区间的范围内要建至少Di 座塔。求最少花费。
输入输出格式
输入格式:第一行为两个数n, m。
接下来一行,有n 个数,描述C 数组。
接下来m 行,每行三个数Li,Ri,Di,描述一个区间。
输出格式:仅包含一行,一个数,为最少花费。
输入输出样例
说明
【样例说明】
位置1 建2 个塔,位置3 建一个塔,位置4 建一个塔。花费1*2+6+3=11。
【数据规模】
对于20%的数据,n≤20,m≤20。
对于50%的数据(包括上部分的数据),Di 全部为1。
对于70%的数据(包括上部分的数据),n≤100,m≤1000。
对于100%的数据,n≤1000,m≤10000,1≤Li≤Ri≤n,其余数据均≤10000。
这个是求线性规划的最小值
可以转化为它的对偶问题,答案是一样的
把原矩阵转置,然后单纯型法
还不需要判断无解和辅助变量
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 double a[1001][10001],eps=1e-8,inf=2e15; 8 int n,m; 9 void pivot(int l,int e) 10 {int i,j; 11 double t=a[l][e]; 12 a[l][e]=1.0; 13 int arr[10001],tot=0; 14 for (i=0;i<=n;i++) 15 if (fabs(a[l][i])>eps) 16 { 17 a[l][i]/=t; 18 tot++; 19 arr[tot]=i; 20 } 21 for (i=0;i<=m;i++) 22 if (i!=l&&fabs(a[i][e])>eps) 23 { 24 t=a[i][e];a[i][e]=0; 25 for (j=1;j<=tot;j++) 26 a[i][arr[j]]-=t*a[l][arr[j]]; 27 } 28 } 29 void simplex() 30 {int i; 31 while (1) 32 { 33 int x=0,y=0; 34 for (i=1;i<=n;i++) 35 if (a[0][i]>eps) 36 {x=i;break;} 37 if (x==0) return; 38 double tmp=inf; 39 for (i=1;i<=m;i++) 40 { 41 if (a[i][x]>eps&&a[i][0]/a[i][x]<tmp) 42 { 43 tmp=a[i][0]/a[i][x]; 44 y=i; 45 } 46 } 47 pivot(y,x); 48 } 49 } 50 int main() 51 {int i,j,u,v,d; 52 cin>>m>>n; 53 for (i=1;i<=m;i++) 54 scanf("%lf",&a[i][0]); 55 for (i=1;i<=n;i++) 56 { 57 scanf("%d%d%d",&u,&v,&d); 58 a[0][i]=d; 59 for (j=u;j<=v;j++) 60 a[j][i]=1; 61 } 62 simplex(); 63 printf("%d\n",(int)(-a[0][0]+0.5)); 64 }