MnZn求助线性规划单纯形
  • 板块题目总版
  • 楼主justalearner
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/7/30 09:07
  • 上次更新2023/11/3 06:58:15
查看原帖
MnZn求助线性规划单纯形
774330
justalearner楼主2023/7/30 09:07

UOJ的这道题

Test#32错误地输出了Infeasible

Test#47与答案相差0.000015

救救蒟蒻吧

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
namespace L
{
	void swap(int &a,int &b) {a^=b,b^=a,a^=b;}
	const int M_Size=1e4+10,N_Size=1e3+10;
	const double eps=1e-14,INF=1e14;
	bool deq(double a,double b){return fabs(a-b)<=eps;}
	int n,m,B[M_Size],N[N_Size];
	double a[M_Size][N_Size],b[M_Size],c[N_Size],v,x[N_Size];
//	void print()
//	{
//		printf("z=%g",v);
//		for(int i=1;i<=n;i++)
//		if(c[i])
//		{
//			if(deq(c[i],-1)) printf("-x_%d",N[i]);
//			else if(deq(c[i],+1)) printf("+x_%d",N[i]);
//			else if(c[i]>0) printf("+%gx_%d",c[i],N[i]);
//			else printf("-%gx_%d",-c[i],N[i]);
//		}
//		printf("\n");
//		for(int i=1;i<=m;i++)
//		{
//			printf("x_%d=%g",B[i],b[i]);
//			for(int j=1;j<=n;j++)
//			if(!deq(a[i][j],0))
//			{
//				if(deq(a[i][j],1)) printf("-x_%d",N[j]);
//				else if(deq(a[i][j],-1)) printf("+x_%d",N[j]);
//				else if(a[i][j]>0) printf("-%gx_%d",a[i][j],N[j]);
//				else printf("+%gx_%d",-a[i][j],N[j]);
//			}
//			printf("\n");
////			printf("%g\n",a[1][1],-a[1][1]);
//		}
//	}
	void pivot(int l,int e)
	{
		swap(B[l],N[e]);
		b[l]/=a[l][e];
		for(int j=1;j<=n;j++)
		if(j!=e) a[l][j]/=a[l][e];
		a[l][e]=1/a[l][e];
//		printf("PIVOTING:\n");
//		print();
		for(int i=1;i<=m;i++)
		if(i!=l)
		{
			b[i]-=a[i][e]*b[l];
			for(int 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];
//			printf("when %d end: %g\n",i,a[1][1]);
		}
//		printf("ALSO PIVOTING(%d,%g):\n",e,a[1][1]);print();
		v+=c[e]*b[l];
		for(int j=1;j<=n;j++)
		if(j!=e) c[j]-=c[e]*a[l][j];
		c[e]=-c[e]*a[l][e];
	}
	double simplex()
	{
//		printf("SIMPLEX:\n");
//		print();
		while(1)
		{
//			printf("!");
			int e=1,l=0;
			for(;e<=n;e++)
			if(c[e]>eps) break;
			if(e==n+1) break;
			double delta=INF;
			for(int i=1;i<=m;i++)
			if(a[i][e]>eps)
			{
				if(b[i]/a[i][e]<delta)
				{
					delta=b[i]/a[i][e];
					l=i;
				}
			}
			if(l==0) return INF;
//			print();
//			printf("pivot %d(%d) %d(%d)\n",l,B[l],e,N[e]);
			pivot(l,e);
//			print();
		}
		memset(x,0,sizeof x);
		for(int i=1;i<=m;i++)
		if(B[i]<=n) x[B[i]]=b[i];
		return v;
	}
	double old_c[N_Size];
//	bool bz[N];
	bool initialize()
	{
//		printf("INITIALIZE:\n");print();
		int k=1;
		for(int i=2;i<=m;i++)
		if(b[i]<b[k]) k=i;
		if(b[k]>=-eps) return true;
		memcpy(old_c,c,sizeof c);
		memset(c,0,sizeof c);
		c[++n]=-1;N[n]=n+m+1;v=0;
		for(int i=1;i<=m;i++) a[i][n]=-1;
//		printf("BEFORE PIVOT:\n");print();
		pivot(k,n);
//		printf("AFTER PIVOT:\n");print();
		if(!deq(simplex(),0)) return false;
		for(int l=1,e;l<=m;l++)
		if(B[l]==n+m+1)
		{
			for(e=1;e<=n;e++)
			if(!deq(a[l][e],0)) break;
			if(e==n+1) printf("Oop! Seems I forget this case...\n");
			pivot(l,e);
			break;
		}
//		print();
		for(int j=1;j<=n;j++)
		if(N[j]==n+m+1)
		{
//			printf("%d\n",j);
			swap(N[j],N[n]);
			for(int i=1;i<=m;i++)
			std::swap(a[i][j],a[i][n]);
			break;
		}
		n--;
		memset(c,0,sizeof c);
		for(int j=1;j<=n;j++)
		if(N[j]<=n) c[j]=old_c[N[j]];
		for(int i=1;i<=m;i++)
		if(B[i]<=n)
		{
			v+=old_c[B[i]]*b[i];
			for(int j=1;j<=n;j++)
			c[j]-=old_c[B[i]]*a[i][j];
		}
		return true;
	}
}
int main()
{
	int t;scanf("%d%d%d",&L::n,&L::m,&t);
	for(int i=1;i<=L::n;i++) scanf("%lf",&L::c[i]),L::N[i]=i;
	for(int i=1;i<=L::m;i++)
	{
		for(int j=1;j<=L::n;j++)
		scanf("%lf",&L::a[i][j]);
		scanf("%lf",&L::b[i]);
		L::B[i]=L::n+i;
	}
	if(!L::initialize()) printf("Infeasible");
	else if(L::simplex()==L::INF) printf("Unbounded");
	else
	{
		printf("%lf",L::v);
		if(t)
		{
			printf("\n");
			for(int i=1;i<=L::n;i++)
			printf("%lf ",L::x[i]);
		}
	}
}
2023/7/30 09:07
加载中...