|
I |
II |
|
设备 原材料A 原材料B |
1 4 0 |
2 0 4 |
8台时 16kg 12kg |
#include
#include
#include
using namespace std;
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 calc(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 check() {
while(1) {
int r, c;
double p = INF;
for(int i = 0; i < m; i++){
if(a[i][n] < p) {
r=i;
p = a[r][n]; // 最右边的常数列
}
}
if(p > -eps) return true; // 都是正数的话可行。
p = 0;
for(int i = 0; i < n; i++) {
if(a[r][i] < p){
c=i;
p = a[r][c]; // 找最小列
}
}
if(p > -eps) return false; // r对应的所有列都是正数,没有负数,无解。
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;
}
}
calc(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(!check()) return 0;
while(1){
int r, c;
double p = 0;
for(int i = 0; i < n; i++) if(a[m][i] > p) {
c = i;
p = a[m][c];
}
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;
calc(r, c);
}
}
};
Simplex solver;
int main()
{
//freopen("cin.txt","r",stdin);
int n, m;
while(~scanf("%d%d", &n, &m)) {
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];
solver.simplex(n,m,x,ans);
ans *= m;
//printf("Nasa can spend %d taka.\n", int(ans+0.5)); // 至少花费的:3.008-->4
printf("Nasa can spend %d taka.\n", (int)floor(ans + 1 - eps));
}
return 0;
}