1. 程式人生 > >[ZJOI2013]防守戰線

[ZJOI2013]防守戰線

接下來 article int strong tro style 描述 col simplex

題目描述

戰線可以看作一個長度為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 }

[ZJOI2013]防守戰線