#include<iostream>
#include"ilcplex/ilocplex.h";

using namespace std;
int main() {
	//Ucitavamo podatke iz datoteke
	ifstream data("cflp.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];
		}

		IloNumArray d(env, n);
		for (int i = 0; i < n; i++)
		{
			data >> d[i];
		}
		IloNumArray M(env, m);
		for (int j = 0; j < m; j++)
		{
			data >> M[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, INFINITY, ILOFLOAT);
		}


		//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: potraznja svakog korisnika mora biti zadovoljena
		for (int i = 0; i < n; i++)
		{
			IloExpr cond1(env);
			for (int j = 0; j < m; j++)
			{
				cond1 += x[i][j];
			}
			model.add(cond1 == d[i]);
			cond1.end();
		}
		//definisemo ogranicenja: gornja ogranicenja za kapaciteta skladista ne smeju  biti prekoracena
		for (int j = 0; j < m; j++)
		{
			IloExpr cond3(env);
			for (int i = 0; i < n; i++)
			{
				cond3 += x[i][j];
			}
			model.add(cond3 <= M[j] * y[j]);
		}


		//definisemo ogranicenja: gornja ogranicenja za potrebe korisnika

		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				IloExpr cond2(env);
				cond2 = x[i][j] - d[i]*y[j];
				model.add(cond2 <= 0);
				cond2.end();
			}

		}

		IloCplex cplex(model);

		cplex.setOut(env.getNullStream());


		if (!cplex.solve()) {
			cout << "Nije moguce resiti.";
		}


		cout << "Vrednost f-je cilja: " << cplex.getObjValue() << endl;
		cout << "Status: " << cplex.getStatus() << endl;
		cout << "Vreme: " << cplex.getTime() << endl;

		ofstream izlaz("cflp_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) {

		cout << "Desila se greska: " << ex;
	}





}
