记录编号 358245 评测结果 AAAAAAAAAA
题目名称 [UVa 10498] 满意值 最终得分 100
用户昵称 Gravatarsxysxy 是否通过 通过
代码语言 C++ 运行时间 0.003 s
提交时间 2016-12-15 10:21:40 内存使用 0.31 MiB
显示代码纯文本
//-std=c99 or g++
//输入 标准型 线性规划,输出目标函数最优解
//输入格式:
/*
 第一行两个整数n, m,表示n个自变量,m个约束
 第二行n个正数,表示目标函数自变量前的系数
 接下来m行,每行n+1个整数
     前n个正数描述了这个约束的自变量前的系数,最后一个正数描述了这个约束 <=号 右边的数值
 例: 
 输入(讲义里面讲单纯形法时用的例子):
 3 3 
 3 1 2
 1 1 3 30
 2 2 5 24
 4 1 2 36
 输出:
 28.00000000
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include <ctype.h>
#define MAXN 50  
#define MAXM 50
//MAXN是变量数的上限,MAXM是约束条件数的上限
const double eps = 1e-9;
int dcmp(double x)
{
    if(x < -eps)return -1;
    else if(x > eps)return 1;
    else return 0;
}
void swap(int *a, int *b)
{
    int c = *a;
    *a = *b;
    *b = c;
}
int n, m; //n个变量,m个约束条件
double A[MAXN][MAXM];
int base[MAXN+MAXM], unbase[MAXM+MAXN]; //基本变量与非基本变量
void pivot(int x, int y) //转动
{
    swap(base+x, unbase+y);
    double k = A[x][y];
    A[x][y] = 1.0;  //前面系数直接变成1.0
    for(int i = 0; i <= n; i++)A[x][i] /= k; //这一行都约掉k
    for(int i = 0; i <= m; i++)  //替换
    {
        if(i != x && dcmp(k = A[i][y]) /* */)
        {
            A[i][0] += (i?-1:1)*k*A[x][0];
            A[i][y] = 0;
            for(int j = 1; j <= n; j++)
                A[i][j] -= k*A[x][j];
        }            
    }
}
int init_simplex()
{
    for(int i = 1; i <= n; i++)unbase[i] = i;  //最开始的n个非基本变量
    for(int i = 1; i <= m; i++)base[i] = n+i; //额外的m个松弛变量
    for(int x = 0, y = 0; ; x = y = 0)
    {
        for(int i = 1; i <= m; i++)
            if(dcmp(A[i][0]) < 0)x = i;
        if(!x)return 1;
        for(int i = 1; i <= n; i++)
            if(dcmp(A[x][i]) < 0)y = i;
        if(!y)return 0; //发现存在b(i) < 0而变量前系数 都大于等于0(注意是 全都 大于等于0)
                       //由于变量具有非负约束,此时整个约束系统无解。
        pivot(x, y);
    }
}
int simplex()
{
    if(!init_simplex())return 0;
    for(int x = 0, y = 0; ; x = y = 0)
    {
        for(int i = 1; i <= n; i++)
            if(dcmp(A[0][i]) > 0)  //找到一个目标函数里前面系数为正数的一个变量
            {                // _______/
                y = i;      //
                break;     //
            }             //
        if(!y)return 1;  //若找不到说明已经找到最优解,返回
        double inf = 1e15;
        for(int i = 1; i <= m; i++)  //找到对y约束最紧的变量
        {
            double t = A[i][0]/A[i][y]; 
            if(dcmp(A[i][y]) > 0 && (!x || t < inf))
            {
                inf = t;
                x = i;
            }
        }
        if(!x)return -1; //无法约束y,此时整个目标函数发散
        pivot(x, y);
    }
}
void test()
{
    freopen("happiness.in", "r", stdin);  //这个文件里面就是讲义里面的例子。
    freopen("happiness.out", "w", stdout);
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++)
        scanf("%lf", A[0]+i);  //A[0]存目标函数,因此最后A[0][0]为目标函数最大值
    for(int i = 1; i <= m; scanf("%lf", A[i++])) //b(i)存到A[i][0]里
        for(int j = 1; j <= n; j++)scanf("%lf", A[i]+j);
    switch(simplex())
    {
        case 1:
            printf("Nasa can spend %.0lf taka.", ceil(m*A[0][0]));
        break;
        case 0:
            puts("No solution");
        break;
        case -1:
            puts("Infinity");
        break;
    }
}
int main()
{
    test();
    return 0;
}