BZOJ1061: [Noi2008]志愿者招募 线性规划之--构造初始可行解
Aug 21, 2015 03:30:38 PM
首要思路是构造辅助线性规划,若最优值为0则删除辅助变量得到存在初始可行解线性规划.
具体看代码吧.
#include<cstdio> #include<cctype> #include<cstring> #include<climits> #include<iostream> #include<algorithm> using namespace std; #define inf 0x3f3f3f3f struct Linear_Programming{ static const int N=10010; static const int M=1010; int n,m,A[M][N],b[M],c[N],v,B[M],nB[N]; int _c[N],_v,Bins[N+M],nBins[N+M],_nB[N]; inline void pivot(int l,int e){ int i,j; for(i=1;i<=n;++i) if(i!=e) A[l][i]/=A[l][e]; b[l]/=A[l][e]; A[l][e]=1/A[l][e]; for(i=1;i<=m;++i) if(i!=l&&A[i][e]!=0){ for(j=1;j<=n;++j) if(j!=e) A[i][j]-=A[i][e]*A[l][j]; b[i]-=A[i][e]*b[l]; A[i][e]*=-A[l][e]; } for(i=1;i<=n;++i) if(i!=e) c[i]-=c[e]*A[l][i]; v+=c[e]*b[l]; c[e]*=-A[l][e]; swap(B[l],nB[e]); } inline int Simplex(){ int i,j,l,e,lim; while(1){ for(e=0,i=1;i<=n;++i) if(c[i]>0){ e=i; break; } if(!e) return v; for(lim=inf,i=1;i<=m;++i) if(A[i][e]>0&&lim>b[i]/A[i][e]){ l=i; lim=b[i]/A[i][e]; } if(lim==inf) return inf; pivot(l,e); } } inline bool init(){ int i,j,l,e,min_b=inf; for(l=0,i=1;i<=m;++i) if(b[i]<min_b){ min_b=b[i]; l=i; } if(min_b>=0) return 1; nB[++n]=0; memcpy(_c,c,sizeof c); _v=v; memcpy(_nB,nB,sizeof nB); memset(c,0,sizeof c); v=0; c[n]=-1; for(i=1;i<=m;++i) A[i][n]=-1; pivot(l,n); if(Simplex()<0) return 0; else{ for(i=1;i<=m;++i) if(B[i]==0){ for(j=1;j<=n;++j){ if(A[i][j]!=0) pivot(i,j); break; } } for(i=1;i<=n;++i) if(nB[i]==0) e=i; --n; for(i=e;i<=n;++i) nB[i]=nB[i+1]; for(i=1;i<=m;++i) for(j=e;j<=n;++j) A[i][j]=A[i][j+1]; for(i=1;i<=n;++i) nBins[nB[i]]=i; for(i=1;i<=m;++i) Bins[B[i]]=i; memset(c,0,sizeof c); v=_v; for(i=1;i<=n;++i){ if(nBins[_nB[i]]) c[nBins[_nB[i]]]+=_c[i]; else{ v+=_c[i]*b[Bins[_nB[i]]]; for(j=1;j<=n;++j) c[j]-=_c[i]*A[Bins[_nB[i]]][j]; } } return 1; } } }g; int main(){ int tim,typ; cin>>tim>>typ; int i,j; for(i=1;i<=tim;++i){ scanf("%d",&g.b[i]); g.b[i]=-g.b[i]; } int s,t,c; for(i=1;i<=typ;++i){ scanf("%d%d%d",&s,&t,&c); for(j=s;j<=t;++j) g.A[j][i]=-1; g.c[i]=-c; } g.n=typ; g.m=tim; for(i=1;i<=g.n;++i) g.nB[i]=i; for(i=1;i<=g.m;++i) g.B[i]=g.n+i; g.init(); cout<<-g.Simplex()<<endl; return 0; }
单纯形法的若干题目 BZOJ3112,3265,3550
Mar 06, 2015 11:00:19 AM
利用一下对偶原理建模什么的都非常裸,就放一下代码吧.
#include<cstdio> #include<cstring> #include<cctype> #include<iostream> #include<algorithm> using namespace std; typedef double f2; #define INF ~0U>>1 struct Solver{ static const int N=10010;//变量个数 static const int M=1010;//限制个数 int n,m; int B[M];//基变量集合 int NB[N];//非基变量集合 f2 c[N],v;//目标函数的各项系数以及常数 f2 A[M][N],b[N];//限制的系数 Solver(){} Solver(int _n,int _m):n(_n),m(_m){} void debug(){ puts("Function"); printf("Maximize "); for(int i=1;i<=n;++i){ if(i>1)putchar('+'); printf("%.2lfx_%d",c[i],NB[i]); } printf("+%.2lf\n",v); puts("Limits"); for(int i=1;i<=m;++i){ printf("x_%d",B[i]); for(int j=1;j<=n;++j)printf("+%.2lfx_%d",A[i][j],NB[j]); printf("<=%.2lf\n",b[i]); } } inline void pivot(int l,int e){//转轴操作,将第l个基变量与第e个非基变量进行交换 int i,j,k; //更改第l个限制,得到x_e与x_l的关系式 b[l]/=A[l][e]; for(i=1;i<=n;++i)if(i!=e)A[l][i]/=A[l][e]; A[l][e]=1/A[l][e]; //将x_e带入,更改剩余的所有限制 for(i=1;i<=m;++i)if(i!=l&&A[i][e]!=0){ b[i]-=b[l]*A[i][e]; for(j=1;j<=n;++j)if(j!=e)A[i][j]-=A[i][e]*A[l][j]; A[i][e]=-A[i][e]*A[l][e]; } //更改目标函数 v+=c[e]*b[l]; for(i=1;i<=n;++i)if(i!=e)c[i]-=c[e]*A[l][i]; c[e]=-c[e]*A[l][e]; swap(B[l],NB[e]); } inline f2 solve(){//得到线性规划的最优解,或者返回无界区域 int i,j,l,e,lim; while(1){ for(e=0,i=1;i<=n;++i)if(c[i]>0){e=i;break;}//寻找最小标号的可行非基变量 if(e==0)return v;//如果不存在这样的非基变量,则已经是最优解,直接返回 //寻找最紧的上界 for(lim=INF,i=1;i<=m;++i)if(A[i][e]>0&&lim>b[i]/A[i][e])l=i,lim=b[i]/A[i][e]; if(lim==INF)return INF;//没有限制,返回无界区域 else pivot(l,e);//否则进行转轴操作 } } }Complex; void output(){Complex.debug();} int n,m; int main(){ scanf("%d%d",&n,&m); register int i,j; Complex.n=m,Complex.m=n; int x; for(i=1;i<=n;++i)scanf("%d",&x),Complex.b[i]=x; int l,r; for(i=1;i<=m;++i){ scanf("%d%d%d",&l,&r,&x); for(j=l;j<=r;++j)Complex.A[j][i]=1; Complex.c[i]=x; } for(i=1;i<=Complex.n;++i)Complex.NB[i]=i; for(i=1;i<=Complex.m;++i)Complex.B[i]=Complex.n+i; //Complex.debug(); printf("%d",(int)Complex.solve()); return 0; }
233剩下的两道题目也很类似.