单纯形 BZOJ3112: [Zjoi2013]防守战线

题面自己上网查。

学了一下单纯形。当然 证明什么的 显然是没去学。不然估计就要残废了

上学期已经了解了 什么叫标准型。 听起来高大上 其实没什么

就是加入好多松弛变量+各种*(-1),使得最后成为一般形式:

  给定A[][],求满足A[i][j]*Xj<=A[i][0];(0<i<=n,0<j<=m)

  使A[0][j]*Xj最大的X[];

如果题面中直接得出的条件是A[i][j]*Xj>=A[i][0]; 使 A[0][j]*Xj最小。

  那么就要用对偶定理,变成 A[i][j]*Yi<=A[0][j] 使A[i][0]*Yi最大

    (实际上只要把A转置一下就好了)

  才写了两题单纯形,具体的怎么求Xi之类的 还没学,这里先放代码,之后再补

 

 1 #include <bits/stdc++.h>
 2 #define N 1005
 3 #define M 10005
 4 using namespace std;
 5 const double eps=0.00000000001;
 6 const double inf=10000000000000;
 7 double a[N][M]; int n,m,x,y;
 8 void simplex(){
 9     while (1){
10         int x=0,y=0; double mn=inf,t;
11         for (int i=1;i<=m;++i) if (a[0][i]>eps) {y=i; break;} //找一个可以使答案增加的xi 只要系数为正就可以
12         if (!y) return;  //没有了 说明答案已经不能再增加了
13         for (int i=1;i<=n;++i) if (a[i][y]>eps&&a[i][0]/a[i][y]<mn) mn=a[x=i][0]/a[i][y];  //对找到的xi ,求出约束最紧的一条约束
14         if (!x) {a[0][0]=-inf; return;}  //表示 可以无限增加
15         t=a[x][y]; a[x][y]=1;
16         for (int i=0;i<=m;++i) a[x][i]/=t;
17         for (int i=0;i<=n;++i) if (i!=x&&abs(a[i][y])>eps){
18             t=a[i][y]; a[i][y]=0; for (int j=0;j<=m;++j) a[i][j]-=t*a[x][j];
19         }
20     }
21 }
22 int main(){
23     scanf("%d%d",&n,&m);
24     for (int i=1;i<=n;++i) scanf("%lf",&a[i][0]);
25     for (int i=1;i<=m;++i){
26         scanf("%d%d%lf",&x,&y,&a[0][i]);
27         for (int j=x;j<=y;++j) ++a[j][i];
28     }
29     simplex();
30     printf("%.0lf",round(-a[0][0]));
31     return 0;
32 }
好短啊

 

18年来补。

UOJ的板子题。。应该比较科学了(忽略中间那个assert)

。还有就是 ,单纯形真的不靠谱,,还要random才能过?。。

 1 #include <bits/stdc++.h>
 2 #define DB long double
 3 using namespace std;
 4 const DB eps=0.000000001;
 5 int n,m,T,k,t,o[45],c[45];
 6 DB tmp[45],a[45][45];
 7 void SWAP(int k,int t){
 8     swap(o[k],c[t]);
 9     DB x=a[k][t]; a[k][t]=1;
10     for (int j=0;j<=n;++j) a[k][j]/=x;
11     for (int i=0;i<=m;++i)
12     if (i!=k){
13         x=a[i][t]; a[i][t]=0;
14         for (int j=0;j<=n;++j) a[i][j]-=x*a[k][j];
15     }
16 }
17 int main(){
18     scanf("%d%d%d",&n,&m,&T);
19     for (int i=1;i<=n;++i) scanf("%Lf",&tmp[i]);
20     for (int i=1;i<=n;++i) c[i]=i;
21     for (int i=1;i<=m;++i){
22         for (int j=1;j<=n;++j) scanf("%Lf",&a[i][j]);
23         scanf("%Lf",&a[i][0]); o[i]=i+n;
24     }
25     k=-1;
26     for (int i=1;i<=m;++i)
27     if (a[i][0]<0&&(k==-1||a[i][0]<a[k][0])) k=i;
28     if (~k){
29         ++n; c[n]=n+m;
30         for (int i=0;i<=m;++i) a[i][n]=-1;
31         SWAP(k,n);
32         while (1){
33             t=-1;
34             for (int j=n;j;--j)
35                 if (a[0][j]>eps) {t=j; if (rand()&1) break;}
36             if (t==-1) break;
37             k=-1;
38             for (int i=1;i<=m;++i)
39             if (a[i][t]>eps)
40             if (k==-1||a[i][0]/a[i][t]<a[k][0]/a[k][t]) k=i;
41             SWAP(k,t);
42         }
43         if (fabs(a[0][0])>eps){
44             puts("Infeasible"); return 0;
45         }
46         k=t=-1;
47         for (int i=1;i<=n;++i) if (c[i]==n+m) t=i;
48         for (int i=1;i<=m;++i) if (o[i]==n+m) k=i;
49         if (~k){
50             for (int j=1;j<=n;++j)
51                 if (fabs(a[k][j])>eps) {t=j; break;}
52             if (t==-1){
53                 assert(0); swap(o[k],o[m]);
54                 for (int j=0;j<=n;++j) swap(a[k][j],a[m][j]);
55                 --m;
56             }else{
57                 SWAP(k,t); swap(c[t],c[n]);
58                 for (int i=1;i<=m;++i) swap(a[i][t],a[i][n]);
59                 --n;
60             }
61         }else{
62             swap(c[t],c[n]);
63             for (int i=1;i<=m;++i) swap(a[i][t],a[i][n]);
64             --n;
65         }
66     }
67     for (int i=0;i<=n;++i) a[0][i]=0;
68     for (int i=1;i<=n;++i)
69     if (c[i]<=n) a[0][i]+=tmp[c[i]];
70     for (int i=1;i<=m;++i)
71     if (o[i]<=n)
72         for (int j=0;j<=n;++j)
73         a[0][j]-=tmp[o[i]]*a[i][j];
74     while (1){
75         t=-1;
76         for (int j=n;j;--j)
77             if (a[0][j]>eps) {t=j; if (rand()&1) break;}
78         if (t==-1) break;
79         k=-1;
80         for (int i=1;i<=m;++i)
81         if (a[i][t]>eps)
82         if (k==-1||a[i][0]/a[i][t]<a[k][0]/a[k][t]) k=i;
83         if (k==-1){
84             puts("Unbounded");
85             return 0;
86         }
87         SWAP(k,t);
88     }
89     printf("%.10Lf\n",-a[0][0]);
90     if (T){
91         for (int i=1;i<=n;++i) tmp[c[i]]=0;
92         for (int i=1;i<=m;++i) tmp[o[i]]=a[i][0];
93         for (int i=1;i<=n;++i) printf("%.10Lf ",tmp[i]);
94         puts("");
95     }
96     return 0;
97 }
天壌を翔る者たち

 

posted @ 2017-03-28 18:16  cyz666  阅读(155)  评论(0编辑  收藏  举报