zoukankan      html  css  js  c++  java
  • UOJ197 线性规划

    传送门

    由于这道题标程GG了所以必不可能AC嘛2333

    单纯形法是一个很玄学的东西qwq

    就是 非标准型 -> 标准型 -> 规范型 -> 松弛型

    一个玄学操作——转轴操作(privot)

    等着学习笔记到时候再补吧先把程序放出来

    写了一些注释方便理解qwq

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<ctime>
    #define inf 20021225
    #define ll long long
    #define db double
    #define eps 1e-8
    using namespace std;
    
    db ans[51],a[51][51];int id[51];int n,m,t;
    
    void privot(int x,int y)
    {
    	swap(id[n+x],id[y]);
    	// 把基变量和非基变量只交换编号
    	// 相当于 id[n+x] x∈(1,m) 存基变量的编号 
    	db tmp=1.0/a[x][y];
    	a[x][y]=1.0;// 原先基变量系数为1 
    	for(int i=0;i<=n;i++)	a[x][i]*=tmp;
    	// 非基变量化基变量系数化一  类似解方程代入法之前的系数化一 
    	for(int i=0;i<=m;i++)
    	{
    		if(i==x||abs(a[i][y])<eps)	continue;
    		db cur=a[i][y]; a[i][y]=0.0;
    		for(int j=0;j<=n;j++)
    			a[i][j]-=a[x][j]*cur;
    	}
    	// 利用新的基变量消元 
    }
    
    bool prework()
    {
    	// 规范型线性规划要求b[i]非负 但是标准型没有这个要求 所以需要预处理 
    	// 把所有b[i]是负的随机匹配几个a[i]是负的然后替换一下 b[i]就变成正的了 
    	while(1)
    	{
    		int x=0,y=0,i;
    		for(i=1;i<=m;i++)	if(a[i][0]<-eps && (!x || rand()&1)) x=i;
    		if(!x)	return true;
    		for(i=1;i<=n;i++)	if(a[x][i]<-eps && (!y || rand()&1)) y=i;
    		if(!y){printf("Infeasible
    ");return false;}//只能取负数无可行域
    		privot(x,y);
    	}
    	return true;
    }
    
    bool simplex()
    {
    	while(1)
    	{
    		int i,x=0,y=0; double mn=1e15;
    		for(i=1;i<=n;i++)	if(a[0][i]>eps){y=i;break;}
    		// 找一个目标系数>0的 
    		if(!y)	break;
    		for(i=1;i<=m;i++)
    			if(a[i][y]>eps&&a[i][0]/a[i][y]<mn)
    				mn=a[i][0]/a[i][y],x=i;
    		// 找限制最严格的 
    		if(!x){printf("Unbounded
    ");return false;} 
    		// 没有限制直接上天(划)无穷大 
    		privot(x,y);
    	}
    	return true;
    }
    
    int main()
    {
    	srand(time(0));
    	scanf("%d%d%d",&n,&m,&t);
    	for(int i=1;i<=n;i++)	scanf("%lf",&a[0][i]),id[i]=i;
    	//初始非基变量i 基变量n+i 
    	for(int i=1;i<=m;i++)
    	{
    		for(int j=1;j<=n;j++)	scanf("%lf",&a[i][j]);
    		scanf("%lf",&a[i][0]);
    	}
    	if(prework()&&simplex())
    	{
    		printf("%.8lf
    ",-a[0][0]);
    		if(t)
    		{
    			for(int i=1;i<=m;i++)	ans[id[n+i]]=a[i][0];
    			for(int i=1;i<=n;i++)	printf("%.8lf ",ans[i]);
    		}
    	} 
    	return 0;
    }
  • 相关阅读:
    MVC 中创建自己的异常处理
    ajax 跨域解决方法
    值传递,引用传递
    值类型,引用类型 结合 栈,堆的理解
    SQL中 ALL 和 ANY 区别的
    SQL中的逻辑运算符
    使用函数输出两个数的最大值
    九句话,送给正在奋斗的我们,每天读一遍
    C语言函数调用简简介
    优秀项目经理的七个习惯
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10321941.html
Copyright © 2011-2022 走看看