#include<ilcplex/ilocplex.h>

ILOSTLBEGIN

//**********************************************p-median**********************************************
int main(int, char**) {
	IloEnv env;
	try {
		IloModel model(env);
		//citamo podatke (m i n)
		IloInt m, n, p, check;

		ifstream data("ulaz_p_med.txt");
		data >> n;
		data >> m;
		data >> p;

		//definisemo parametre
		IloArray<IloNumArray> C(env, n);
		for (int i = 0; i < n; i++)
			C[i] = IloNumArray(env, m);

		//citamo podatke
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++)
				data >> C[i][j];

		data >> check;

		if (check == 777)
			cout << "Podaci su uspesno ucitani." << endl;
		else
			cout << "Greska pri ucitavanju podataka." << endl;

		//definisemo promenljive
		IloArray<IloNumVarArray> x(env, n);
		for (int i = 0; i < n; i++) {
			x[i] = IloNumVarArray(env, m, 0, 1, ILOBOOL);
		}

		IloNumVarArray y(env, m, 0, 1, ILOBOOL);

		//Funkcija cilja
		IloExpr fo(env);
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++)
				fo += C[i][j] * x[i][j];

		model.add(IloMinimize(env, fo));

		//ogranicenja
		IloExpr Expr(env);

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				Expr += x[i][j];
			}
			model.add(Expr == 1);
			Expr.end();
			Expr = IloExpr(env);
		}


		IloExpr Expr2(env);

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				Expr2 = x[i][j] - y[j];
				model.add(Expr2 <= 0);
				Expr2.end();
				Expr2 = IloExpr(env);
			}
		}


		IloExpr Expr3(env);

		for (int j = 0; j < m; j++) {
			Expr3 += y[j];
		}
		model.add(Expr3 == p);
		Expr3.end();
		Expr3 = IloExpr(env);


		//odavde nadole standardno
		IloCplex cplex(env);
		cplex.setOut(env.getNullStream());
		cplex.extract(model);
		cplex.exportModel("model_p-med.lp");

		if (!cplex.solve()) {
			env.error() << "Nije moguce resiti :-(" << endl;
			throw(-1);
		}
		//ispisi promenljive
		ofstream izlaz("izlaz_p-med.txt");
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				izlaz << cplex.getValue(x[i][j]) << " ";
			}
			izlaz << endl;
		}
		for (int j = 0; j < m; j++) {
			izlaz << cplex.getValue(y[j]) << " ";
		}
		izlaz << endl;
		env.out() << "Status: " << cplex.getStatus() << endl;
		env.out() << "Vrednost funkcije cilja: " << cplex.getObjValue() << endl;
		env.out() << "Vreme izvrsavanja: " << cplex.getTime() << endl;
	}
	catch (IloException& ex) {
		cerr << "Error Cplex: " << ex << endl;
	}
}