2017.10.8 志愿者招募 失败总结

。这个题要是想用费用流写的话就太难了。

所以就要考虑统筹学的另一个工具--单纯形

实际上。很多网络流解决的都是线性规划的问题,,这些问题很多都可以用单纯形解

关于单纯形的学习资料网上很详细了。。这里就说一些代码实现上的小技巧

1、 换完基变量和非基变量,原来非基变量的位置直接赋值为基变量的值

2、操作的形式是    Xn+i  +  a1*X1  + a2* X2  + a3*X3   =    bi

带入的形式是   X1  =  bi/a1  -  Xn+i / a1  -  a2* X2 / a1  -  a3*X3 / a1

3、注意eps

4、这个题是对偶问题,,需要将原矩阵A 转置    b、c互换。。。。。。。


码:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define eps 1e-7
double b[10005],a[10005][1005],c[1005],ans;
int n,m,i,j,x,y;
void pvt(int o,int wz)
{//cout<<endl<<o<<" "<<wz<<endl;
	int i,j;
	b[wz]/=a[wz][o];
	for(i=1;i<=n;i++)
		if(i!=o)
			a[wz][i]/=a[wz][o];			
a[wz][o]=1.0/a[wz][o];
    for(i=1;i<=m;i++)
if(i!=wz&&fabs(a[i][o])>eps)
{
	b[i]-=b[wz]*a[i][o];
//	cout<<" "<<i<<"  ";
	for(j=1;j<=n;j++)
	if(j!=o)
	a[i][j]-=a[wz][j]*a[i][o];
	a[i][o]=-a[i][o]*a[wz][o];//	cout<<a[i][o]<<" ";
}//cout<<endl;
	ans+=b[wz]*c[o];
//	cout<<ans<<" ";
	for(i=1;i<=n;i++)
		if(i!=o)
	c[i]-=c[o]*a[wz][i];	
c[o]=-a[wz][o]*c[o];	
}
void smp()
{
	while(1)
	{
		int e,lin;
		for(e=1;e<=n;e++)if(c[e]>eps)break;//找还没有解决的点 
		if(e==n+1)break;
	//	cout<<endl<<e<<endl;
		double o=1e10;
		for(i=1;i<=m;i++)
		if(a[i][e]>eps&&(b[i]/a[i][e])<o)//找最小的 约束 
		{
			o=(b[i]/a[i][e]);
			lin=i;		
		}
		//	cout<<" "<<b[lin]<<" "<<a[lin][e];
         pvt(e,lin);
	}
}
int main()
{
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%lf",&c[i]);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%lf",&x,&y,&b[i]);
		for(j=x;j<=y;j++)
		a[i][j]=1;		
	}
	//for(i=1;i<=n;i++)printf("%.1lf ",c[i]);
	 smp();
	printf("%.0lf",ans);	
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值