[bzoj1061][Noi2008]志愿者招募

本文介绍了NOI2008志愿者招募的问题,被标记为裸题,主要涉及使用单纯形算法进行求解。
摘要由CSDN通过智能技术生成

裸题…
直接跑单纯形
Orz w_yqts

#include <bits/stdc++.h>
using namespace std;
#define inf 10000000000.0
#define eps (1e-9)
#define db double
#define N 1005
#define M 10005
db A[M][N],b[M],c[N],v;
int n,m;
inline void pivot(int l,int e)//转轴操作
{
    //B:基变量,l:当前选中基变量下标
    //N:非基变量,e:当前选中非基变量下标
    //基变量的系数为1
    b[l]/=A[l][e];//限制的修改
    for (int i=1;i<=n;++i) if (i!=e) A[l][i]/=A[l][e];//同除以A[l][e]
    A[l][e]=1/A[l][e];//现基变量(原基变量B[l])的系数变为1/A[l][e](同除以A[l][e])
    //修改第l个等式,使它符合基变量(从B[l]变为N[e])的变换
    for (int i=1;i<=m;++i)//修改其它等式,消除原非基变量N[e],加入原基变量B[l]
    if (i!=l && abs(A[i][e])>eps)
    {
        //将第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];//新的非基变量加入
    }
    //答案计算公式修改为另一个等价的公式(将N[e]替换为B[l])
    v+=c[e]*b[l];//修改公式中的常数项
    for (int 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],N[e]);//交换原基变量与原非基变量
}
inline void simplex()
{
    int l,e;
    while (1)
    {
        for (e=1;e<=n;++e)
        if (c[e]>eps) break;
        if (e>n) break;
        db t=inf;
        for (int i=1;i<=m;++i)
        if (A[i][e]>eps && b[i]/A[i][e]<t)
        {
            t=b[i]/A[i][e];
            l=i;
        }
        pivot(l,e);
    }
}
int main()
{
    cin>>n>>m;
    for (int i=1;i<=n;++i) scanf("%lf",&c[i]);
    for (int i=1;i<=m;++i)
    {
        int x,y;
        scanf("%d%d%lf",&x,&y,&b[i]);
        for (int j=x;j<=y;++j) ++A[i][j];
    }
    simplex();
    printf("%.0lf\n",v);
    //for (int i=1;i<=n;++i) cout<<c[i]<<' ';cout<<endl;for (int i=1;i<=m;++i){for (int j=1;j<=n;++j) cout<<A[i][j]<<' ';cout<<b[i]<<endl;}
    return 0;
}
/*
Maximize=3x1+x2+2x3
S.T.
x4+x1+x2+3x3=30
x5+2x1+2x2+5x3=24
x6+4x1+x2+2x3=36
B={4,5,6}
N={1,2,3}
A={
    {1,1,3}
    {2,2,5}
    {4,1,2}
  }
b={30,24,36}
c={3,1,2}
l=3,e=1
*/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值