学了下单纯形法解线性规划
看起来好像并不是特别难,第二个code有注释。我还有...*=-....这个不是特别懂
第一个是正常的,第二个是解对偶问题的
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; const double eps=1e-7; int n,m; double sum; double a[1100][1100],b[1100],c[1100]; void pivot(int o,int e) { b[o]/=a[o][e]; for(int i=1;i<=n;i++) if(i!=e)a[o][i]/=a[o][e]; a[o][e]=1/a[o][e]; for(int i=1;i<=m;i++) if(i!=o&&fabs(a[i][e])>eps) { b[i]-=b[o]*a[i][e]; for(int j=1;j<=n;j++) if(j!=e)a[i][j]-=a[o][j]*a[i][e]; a[i][e]*=-a[o][e]; } sum+=c[e]*b[o]; for(int i=1;i<=n;i++) if(i!=e)c[i]-=a[o][i]*c[e]; c[e]*=-a[o][e]; } void simplex() { int e,o; double d; while(1) { d=0; for(int i=1;i<=n;i++) if(c[i]>d)d=c[i],e=i; if(d==0)return ; d=(1<<30); for(int i=1;i<=m;i++) if(a[i][e]>eps&&d>b[i]/a[i][e]) d=b[i]/a[i][e],o=i; if(d==(1<<30)){sum=(1<<30);return ;} pivot(o,e); } } int main() { int K; scanf("%d%d",&n,&K);m=2*n+1;n*=3; for(int i=1;i<=n;i++)scanf("%lf",&c[i]); for(int i=1;i<=m;i++) { b[i]=K; for(int j=1;j<=n/3;j++)a[i][i+j-1]++; } for(int i=1;i<=n;i++) b[m+i]=1,a[m+i][i]++; m+=n; sum=0;simplex(); printf("%.0lf\n",sum); return 0; }
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; const double eps=1e-7; int n,m; double sum; double a[1100][11000],b[11000],c[1100]; //解的过程中,由于基变量xi=ci,所以c也代表放在当前约束的基变量取值 void pivot(int o,int e)//把作为第o个约束的基变量用e替换 { c[o]/=a[o][e];//没有替换之前,e的取值被当前限制,是c[o]/a[i][e],先令x=c for(int i=1;i<=m;i++)//把e的系数消掉,其实常数项c也是同理的 if(i!=e)a[o][i]/=a[o][e]; a[o][e]=1/a[o][e];//难点!取倒数相当于保留了自己的常数项,而除以了上一个的常数项,这样下面就可以直接消除上一个的影响了 for(int i=1;i<=n;i++) if(i!=o&&fabs(a[i][e])>eps)//对于其它的约束条件,把离基的变量用进基的变量替代 { c[i]-=c[o]*a[i][e]; for(int j=1;j<=m;j++) if(j!=e)a[i][j]-=a[o][j]*a[i][e]; a[i][e]*=-a[o][e]; } sum+=b[e]*c[o];//系数乘以值 for(int i=1;i<=m;i++)//对于第i个变量当前已经用了b[e]*a[o][i]来贡献答案了 if(i!=e)b[i]-=a[o][i]*b[e]; b[e]*=-a[o][e]; } void simplex() { int e,o; double d; while(1) { d=0;//找进基的变量 for(int i=1;i<=m;i++)//基变量的b一定<=0,在非基变量中找一个对答案贡献最大(系数最大)的进基 if(b[i]>d)d=b[i],e=i; if(d==0)return ; d=(1<<30);//找离基的变量,进基变量系数的非负比要最小 for(int i=1;i<=n;i++)//找对e的最小约束(即用此新角点截距最小,也就是当前e的取值被这个约束条件约束)离基 if(a[i][e]>eps&&d>c[i]/a[i][e]) d=c[i]/a[i][e],o=i; if(d==(1<<30)){sum=(1<<30);return ;} pivot(o,e); } } int main() { int l,r; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%lf",&c[i]); memset(a,0,sizeof(a)); for(int i=1;i<=m;i++) { scanf("%d%d%lf",&l,&r,&b[i]); for(int j=l;j<=r;j++)a[j][i]++; } simplex(); printf("%.0lf\n",sum); return 0; }
---恢复内容结束---
原文地址:https://www.cnblogs.com/AKCqhzdy/p/10203519.html
时间: 2024-10-12 01:16:19