例题6.22 食物分配 UVa10498

来源:互联网 发布:网站源码破解版 编辑:程序博客网 时间:2024/04/29 06:35

1.题目描述:点击打开链接

2.解题思路:本题是一道线性规划题,利用单纯形法解决。具体过程见代码。

3.代码:

#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<bitset>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cctype>#include<complex>#include<functional>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define me(s)  memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)typedef long long ll;typedef unsigned int uint;typedef unsigned long long ull;typedef pair <int, int> P;const int maxm = 500; // 约束数目上限const int maxn = 500; // 变量数目上限const double INF = 1e100;const double eps = 1e-10;struct Simplex {  int n; // 变量个数  int m; // 约束个数  double a[maxm][maxn]; // 输入矩阵  int B[maxm], N[maxn]; // 算法辅助变量  void pivot(int r, int c) {    swap(N[c], B[r]);    a[r][c] = 1 / a[r][c];    for(int j = 0; j <= n; j++) if(j != c) a[r][j] *= a[r][c];    for(int i = 0; i <= m; i++) if(i != r) {      for(int j = 0; j <= n; j++) if(j != c) a[i][j] -= a[i][c] * a[r][j];      a[i][c] = -a[i][c] * a[r][c];    }  }  bool feasible() {    for(;;) {      int r, c;      double p = INF;      for(int i = 0; i < m; i++) if(a[i][n] < p) p = a[r = i][n];      if(p > -eps) return true;      p = 0;      for(int i = 0; i < n; i++) if(a[r][i] < p) p = a[r][c = i];      if(p > -eps) return false;      p = a[r][n] / a[r][c];      for(int i = r+1; i < m; i++) if(a[i][c] > eps) {        double v = a[i][n] / a[i][c];        if(v < p) { r = i; p = v; }      }      pivot(r, c);    }  }  // 解有界返回1,无解返回0,无界返回-1。b[i]为x[i]的值,ret为目标函数的值  int simplex(int n, int m, double x[maxn], double& ret) {    this->n = n;    this->m = m;    for(int i = 0; i < n; i++) N[i] = i;    for(int i = 0; i < m; i++) B[i] = n+i;    if(!feasible()) return 0;    for(;;) {      int r, c;      double p = 0;      for(int i = 0; i < n; i++) if(a[m][i] > p) p = a[m][c = i];      if(p < eps) {        for(int i = 0; i < n; i++) if(N[i] < n) x[N[i]] = 0;        for(int i = 0; i < m; i++) if(B[i] < n) x[B[i]] = a[i][n];        ret = -a[m][n];        return 1;      }      p = INF;      for(int i = 0; i < m; i++) if(a[i][c] > eps) {        double v = a[i][n] / a[i][c];        if(v < p) { r = i; p = v; }      }      if(p == INF) return -1;      pivot(r, c);    }  }};//////////////// 题目相关#include<cmath>Simplex solver;int main() {  int n, m;  while(scanf("%d%d", &n, &m) == 2) {    for(int i = 0; i < n; i++) scanf("%lf", &solver.a[m][i]); // 目标函数    solver.a[m][n] = 0; // 目标函数常数项    for(int i = 0; i < m; i++)      for(int j = 0; j < n+1; j++)        scanf("%lf", &solver.a[i][j]);    double ans, x[maxn];    assert(solver.simplex(n, m, x, ans) == 1);    ans *= m;    printf("Nasa can spend %d taka.\n", (int)floor(ans + 1 - eps));  }  return 0;}

0 0
原创粉丝点击