zoukankan      html  css  js  c++  java
  • UOJ179 线性规划

    Description

    这是一道模板题。
    本题中你需要求解一个标准型线性规划:
    (n)个实数变量(x_1,x_2,cdots,x_n)(m)条约束,其中第(i)条约束形如(sum_{j=1}^{n}a_{ij}x_{j} le b_{i})
    此外这(n)个变量需要满足非负性限制,即(x_{j}≥0)
    在满足上述所有条件的情况下,你需要指定每个变量(x_{j})的取值,使得目标函数(F=sum^n_{j=1}c_jx_j)的值最大。

    Input

    第一行三个正整数 (n,m,t)。其中(t in {0,1})
    第二行有(n)个整数(c_1,c_2,cdots,c_n),整数间均用一个空格分隔。
    接下来mm行,每行代表一条约束,其中第(i)行有(n+1)个整数(a_{i1},a_{i2},cdots,a_{in},b_{i}),整数间均用一个空格分隔。

    Output

    如果不存在满足所有约束的解,仅输出一行"Infeasible"。
    如果对于任意的(M),都存在一组解使得目标函数的值大于(M),仅输出一行"Unbounded"。
    否则,第一行输出一个实数,表示目标函数的最大值(F)。当第一行与标准答案的相对误差或绝对误差不超过(10^{−6}),你的答案被判为正确。
    如果(t=1),那么你还需要输出第二行,用空格隔开的(n)个非负实数,表示此时(x_{1},x_{2},⋯,x_{n})的取值,如有多组方案请任意输出其中一个。
    判断第二行是否合法时,我们首先检验(F−sum^{n}_{j=1}c_{j}x_j)是否为(0),再对于所有(i),检验(min{0,b_i−sum^n_{j=1}a_{ij}x_{j} })是否为(0)。检验时我们会将其中大于(0)的项和不大于(0)的项的绝对值分别相加得到(S+)(S−),如果(S+)(S−)的相对误差或绝对误差不超过(10^{−6}),则判为正确。
    如果(t=0),或者出现Infeasible或Unbounded时,不需要输出第二行。

    Sample Input

    2 2 1
    1 1
    2 1 6
    -1 2 3

    Sample Output

    4.2
    1.8 2.4

    标准线性规划板子题。
    具体做法戳这里
    贴份代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    
    #define maxn (30)
    #define eps (1e-8)
    
    int N,M,op,tot,q[maxn],idx[maxn],idy[maxn]; double a[maxn][maxn],A[maxn];
    
    inline void pivot(int x,int y)
    {
    	swap(idy[x],idx[y]);
    	double tmp = a[x][y]; a[x][y] = 1/a[x][y];
    	for (int i = 0;i <= N;++i) if (y != i) a[x][i] /= tmp;
    	tot = 0; for (int i = 0;i <= N;++i) if (i != y&&(a[x][i] > eps||a[x][i] < -eps)) q[++tot] = i;
    	for (int i = 0;i <= M;++i)
    	{
    		if ((x == i)||(a[i][y] < eps&&a[i][y] > -eps)) continue;
    		for (int j = 1;j <= tot;++j) a[i][q[j]] -= a[x][q[j]]*a[i][y];
    		a[i][y] = -a[i][y]/tmp;
    	}
    }
    
    int main()
    {
    	freopen("179.in","r",stdin);
    	freopen("179.out","w",stdout);
    	scanf("%d %d %d",&N,&M,&op); srand(233);
    	for (int i = 1;i <= N;++i) scanf("%lf",a[0]+i);
    	for (int i = 1;i <= M;++i)
    	{
    		for (int j = 1;j <= N;++j) scanf("%lf",a[i]+j);
    		scanf("%lf",a[i]);
    		
    	}
    	for (int i = 1;i <= N;++i) idx[i] = i;
    	for (int i = 1;i <= M;++i) idy[i] = i+N;
    	while (true)
    	{
    		int x = 0,y = 0;
    		for (int i = 1;i <= M;++i) if (a[i][0] < -eps&&((!x)||(rand()&1))) x = i; if (!x) break;
    		for (int i = 1;i <= N;++i) if (a[x][i] < -eps&&((!y)||(rand()&1))) y = i; if (!y) return puts("Infeasible"),0;
    		pivot(x,y);
    	}
    	while (true)
    	{
    		int x = 0,y = 0; double mn = 1e15;
    		for (int i = 1;i <= N;++i) if (a[0][i] > eps) { y = i; break; } if (!y) break;
    		for (int i = 1;i <= M;++i) if (a[i][y] > eps && a[i][0]/a[i][y] < mn) mn = a[i][0]/a[i][y],x = i; if (!x) return puts("Unbounded"),0;
    		pivot(x,y);
    	}
    	printf("%.8lf
    ",-a[0][0]); if (!op) return 0;
    	for (int i = 1;i <= M;++i) if (idy[i] <= N) A[idy[i]] = a[i][0];
    	for (int i = 1;i <= N;++i) printf("%.8lf ",A[i]);
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    12 KLT算法
    1- js vue.js
    复用代码
    计算两个日期相隔的天数(jodd)
    [转]ORA-00907: 缺失右括号
    [转]sql server 数据库日期格式化函数
    [Oralce]Oralce格式化日期
    myeclipse内存配置
    cookie 编码问题
    [转]Oracle 操作字符串的函数
  • 原文地址:https://www.cnblogs.com/mmlz/p/6075845.html
Copyright © 2011-2022 走看看