#include<iostream>
#include"ilcplex/ilocplex.h";

using namespace std;


int main() {

	//Ucitavamo podatke iz datoteke
	ifstream data("uflp.txt");

	IloEnv env;
	try {
		IloModel model(env);

		IloInt n, m, check;

		data >> n;
		data >> m;

		IloNumArray f(env, m);
		for (int j = 0; j < m; j++)
		{
			data >> f[j];
		}
		IloArray<IloNumArray> c(env, n);

		for (int i = 0; i < n; i++)
		{
			c[i] = IloNumArray(env, m);
			for (int j = 0; j < m; j++)
			{
				data >> c[i][j];
			}

		}

		data >> check;
		if (!check == 777)
			cout << "Greska prilikom ucitavanja podataka.";


		//definisemo promenljive

		IloNumVarArray y(env, m, 0, 1, ILOBOOL);
		IloArray<IloNumVarArray> x(env, n);

		for (int i = 0; i < n; i++)
		{
			x[i] = IloNumVarArray(env, m, 0, 1, ILOBOOL);
		}


		//definisemo f-ju cilja

		IloExpr fc(env);

		for (int j = 0; j < m; j++)
		{
			fc += f[j] * y[j];
			for (int i = 0; i < n; i++)
			{
				fc += c[i][j] * x[i][j];
			}

		}
		model.add(IloMinimize(env, fc));

		//definisemo ogranicenja: svaki korisnik se pridruzeje tacno jednom usluznom centru
		for (int i = 0; i < n; i++)
		{
			IloExpr cond1(env);
			for (int j = 0; j < m; j++)
			{
				cond1 += x[i][j];
			}
			model.add(cond1 == 1);
			cond1.end();
		}
		//definisemo ogranicenja: zabranjeno je pridruzivanje korisnika lokacijama na kojim nisu centri(y_j=0)
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				IloExpr cond2(env);
				cond2 = x[i][j] - y[j];
				model.add(cond2 <= 0);
				cond2.end();
			}

		}

		IloCplex cplex(model);

		cplex.setOut(env.getNullStream());


		if (!cplex.solve()) {
			cerr << "Nije moguce resiti.";
			throw(-1);
		}

		//Ispisujemo na standardni izlaz i u datoteku
		cout << "Vrednost f-je cilja: " << cplex.getObjValue() << endl;
		cout << "Status: " << cplex.getStatus() << endl;
		cout << "Vreme: " << cplex.getTime() << endl;

		ofstream izlaz("uflp_izlaz.txt");

		izlaz << "Vrednost f-je cilja: " << cplex.getObjValue() << endl;
		izlaz << "Status: " << cplex.getStatus() << endl;
		izlaz << "Vreme: " << cplex.getTime() << endl;

		izlaz << "Resenje: " << endl;
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				izlaz << cplex.getValue(x[i][j]) << " ";
			}
			izlaz << endl;
		}


	}
	catch (IloException& ex) {
	
		cerr << "Desila se greska: " << ex;
	}



	

}