1. 程式人生 > >BZOJ 1061 [Noi2008]志願者招募 線性規劃

BZOJ 1061 [Noi2008]志願者招募 線性規劃

題意:連結

方法:線性規劃

解析:

不妨對樣例加以闡釋

3 3

2 3 4

1 2 2

2 3 5

3 3 2

不妨設Xi代表第i種志願者選Xi個人

那麼顯然,這題的限制為

X1>=2

X1+X2>=3

X2+X3>=4

而我們要做的是使2X1+5X2+2X3最小化

Xi>=0

但這顯然沒有基本可行解,那麼就不能用單純形搞了嗎?

並不是

有一個強大的東西叫對偶原理

什麼是對偶原理呢?

對於本人的程式碼

設矩陣a[i][j]

其中a[0]
[i]
代表目標函式的係數

a[i][0]代表第i個限制的常數項

a[i][j]代表第i個限制的第j個非基本變數的係數

那麼對偶原理相當於什麼呢?

將這個a轉置,並且轉置後形成的矩陣又能滿足一個線性規劃。

而這個線性規劃是一個標準型線性規劃

我們只需要求一下轉置後矩陣對應的標準型線性規劃的目標函式的最大值即可,此時這個值同時代表原線性規劃的最小值。

至於證明?

好像算導有吧。

我並不會。

總之這道題就可以解了。

程式碼:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> #define N 1010 #define M 10010 #define INF 0x7f7f7f7f using namespace std; int n,m; double a[M][N]; int check() { for(int i=1;i<=n;i++) if(a[0][i]>0)return i; return 0; } void Simplex() { while(int t=check()) { double limit=INF; int choseline; for
(int i=1;i<=m;i++) { if(a[i][t]<=0)continue; if(a[i][0]/a[i][t]<limit)limit=a[i][0]/a[i][t],choseline=i; } if(limit==INF){a[0][0]=INF;break;} double di=a[choseline][t]; for(int i=0;i<=n;i++) { if(i==t)a[choseline][i]/=di; a[choseline][i]/=di; } for(int i=0;i<=m;i++) { if(i==choseline||!a[i][t])continue; if(i==0)a[i][0]+=a[choseline][0]*a[i][t]; else a[i][0]-=a[i][t]*a[choseline][0]; double l=a[i][t]; for(int j=1;j<=n;j++) { if(j==t)a[i][j]=-l*a[choseline][t]; else a[i][j]-=l*a[choseline][j]; } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%lf",&a[0][i]); for(int i=1;i<=m;i++) { int s,t; scanf("%d%d",&s,&t); for(int j=s;j<=t;j++)a[i][j]=1; scanf("%lf",&a[i][0]); } Simplex(); printf("%.0lf\n",a[0][0]); }