[ZJOI2013]防守战线

题目描述

战线可以看作一个长度为n 的序列,现在需要在这个序列上建塔来防守敌兵,在序列第i 号位置上建一座塔有Ci 的花费,且一个位置可以建任意多的塔,费用累加计算。有m 个区间[L1, R1], [L2, R2], …, [Lm, Rm],在第i 个区间的范围内要建至少Di 座塔。求最少花费。

输入输出格式

输入格式:

第一行为两个数n, m。

接下来一行,有n 个数,描述C 数组。

接下来m 行,每行三个数Li,Ri,Di,描述一个区间。

输出格式:

仅包含一行,一个数,为最少花费。

输入输出样例

输入样例#1: 复制
5 3
1 5 6 3 4
2 3 1
1 5 4
3 5 2
输出样例#1: 复制
11

说明

【样例说明】

位置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 }

 

posted @ 2018-02-21 17:56  Z-Y-Y-S  阅读(507)  评论(0编辑  收藏  举报