[BZOJ1061]-[Noi2008]志愿者招募-单纯形

说在前面

学习单纯形
让me切身体会到了:书读百遍,其义自见
内心mmp


题目

BZOJ1061传送门
看题可进传送门


解法

懒得写解法了……(要是写,估计又是长篇大论的,me才懒得写…)
这个题,按照题意是,代价取min,然后是大于等于限制
直接把这个问题对偶一下,就变成了线性规划的标准型,就可以直接单纯形了

然而这个复杂度真是玄学的可以,一次pivot操作就是1e7级别的= =???
总操作次数还是无保证的(非多项式)要卡岂不是可以卡上天
不是很理解…还请大佬指教

关于对偶,可以去看一看
2016集训队论文《浅谈线性规划与对偶问题——董克凡》

关于全幺模矩阵,可以看一看Candy的这两篇(me没看懂,弃了)
传送门1
传送门2

关于单纯形的学习资料,可以去看一看
fjzzq’s blog
hrwhisper’s blog


下面是自带大常数的代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

int N , M ;
double a[10005][1005] , eps = 1e-8 ;

int dcmp( double x ){ return x < -eps ? -1 : x > eps ; }

void pivot( int r , int c ){ // r is Basis
    double tmp = - a[r][c] ; a[r][c] = -1 ;
    register int j ;
    for( j = 0 ; j <= N ; j ++ ) a[r][j] /= tmp ;
    for( int i = 0 ; i <= M ; i ++ ){
        if( dcmp( a[i][c] ) == 0 || i == r ) continue ;
        tmp = a[i][c] ; a[i][c] = 0 ;
        for( j = 0 ; j <= N ; j ++ )
            a[i][j] += tmp * a[r][j] ;
    }
}

void solve(){
    while( true ){
        int x = 0 , y = 0 ;
        double rem = 1e15 ;
        for( int i = 1 ; i <= N && !x ; i ++ )
            if( a[0][i] > eps ) x = i ;
        if( !x ) break ;
        for( int i = 1 ; i <= M ; i ++ )
            if( a[i][x] <-eps && rem > - a[i][0] / a[i][x] ) 
                rem = - a[i][0] / a[i][x] , y = i ;
        if( !y ) break ; // this will not happen
        pivot( y , x ) ;
    } printf( "%.0f" , a[0][0] ) ;
}

int main(){
    scanf( "%d%d" , &N , &M ) ;
    for( int i = 1 ; i <= N ; i ++ ) scanf( "%lf" , &a[0][i] ) ;
    for( int i = 1 ; i <= M ; i ++ ){
        int st , ed ;
        scanf( "%d%d%lf" , &st , &ed , &a[i][0] ) ;
        for( int j = st ; j <= ed ; j ++ ) a[i][j] = -1 ;
    } solve() ;
}

猜你喜欢

转载自blog.csdn.net/Izumi_Hanako/article/details/80048718