int id[Maxn * 2];//id[n+1]~id[n+m]记录了m个约束对应的主元?? double a[Maxn][Maxn]; //第一维是限制,B集合 //第二维是元素,N集合 //a[0][xx] -> c 目标函数系数 //a[xx][0] -> b 限制等式常数 //a[xx][yy] -> A 限制等式系数向量 //最大化 sigma(ci*xi),i属于N //限制 xj=bj-sigma(aji*xi) ,j属于B
doublemyabs(double x){ return x > 0 ? x : -x; }
voidPivot(int l, int e) { //转轴l和e swap(id[n + l], id[e]); double t = a[l][e]; a[l][e] = 1; for (int j = 0; j <= n; j++) a[l][j] /= t; for (int i = 0; i <= m; i++) if (i != l && (myabs(a[i][e]) > eps))//行不等于l,并且a[i][e] != 0 { t = a[i][e]; a[i][e] = 0; for (int j = 0; j <= n; j++) a[i][j] -= a[l][j] * t; } }
//初始化-辅助问题 boolinit() { while (1) { int e = 0, l = 0; for (int i = 1; i <= m; i++) if ((a[i][0] < -eps) && (!l || (rand() & 1)))//在所有bi<0中随机选择一个作为换出,没加括号之前,烂代码的代表!!小于号和与运算的优先级 l = i; if (!l)//bi都大于0,初始化结束。 break; for (int j = 1; j <= n; j++) if ((a[l][j] < -eps) && (!e || (rand() & 1)))//在所有a[i]中随机选择一个作为换出 e = j; if (!e)//bl小于0但是这一行的alj都大于0,无解,可行域为空 { printf("Infeasible\n"); return0; } Pivot(l, e); } return1; }
//最优化 boolsimplex() { while (1) { int l = 0, e = 0; double mn = INF; for (int j = 1; j <= n; j++) if (a[0][j] > eps)//大于0 { e = j; break; } if (!e) break; //如果目标变量c都小于0 找到答案 for (int i = 1; i <= m; i++) if ((a[i][e] > eps) && (a[i][0] / a[i][e] < mn)) mn = a[i][0] / a[i][e], l = i; //找a[i][0]/a[i][e]最小的i进行转轴 if (!l) { printf("Unbounded\n"); return0; } //如果所有的a[i][e]都小于0,说明最优值正无穷 Pivot(l, e); } return1; }
double ans[Maxn];
intmain() { srand(time(0)); int t; scanf("%d%d%d", &n, &m, &t); 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][0]); } for (int i = 1; i <= n; i++) id[i] = i; if (init() && simplex()) { printf("%.8lf\n", -a[0][0]); if (t) { for (int i = 1; i <= m; i++) ans[id[n + i]] = a[i][0]; for (int i = 1; i <= n; i++) printf("%.8lf ", ans[i]); } } //system("pause"); return0; }