#include<iostream>
#include"ilcplex/ilocplex.h";

using namespace std;

int main(int, char**) { 

	ifstream data("usahlp2.txt");
	IloEnv(env);
	try {
		IloModel model(env);
		IloInt m, check;
		IloNum lambda, alpha, delta;

		data >> m;
		IloArray<IloNumArray> c(env, m);


		for (int i = 0; i < m; i++)
		{
			c[i] = IloNumArray(env, m);
			for (int j = 0; j < m; j++)
			{
				data >> c[i][j];
			}

		}

		IloArray<IloNumArray> w(env, m);


		for (int i = 0; i < m; i++)
		{
			w[i] = IloNumArray(env, m);
			for (int j = 0; j < m; j++)
			{
				data >> w[i][j];
			}

		}

		IloNumArray f(env, m);
		for (int i = 0; i < m; i++)
		{
			data >> f[i];
		}
		data >> lambda;
		data >> alpha;
		data >> delta;
		data >> check;

		if (check == 777)
			cout << "Ucitani su podaci." << endl;
		else
			cout << "Nisu ucitani podaci.";

		IloNumArray O(env, m);
		IloNumArray D(env, m);

		for (int i = 0; i < m; i++)
		{

			for (int j = 0; j < m; j++)
			{
				O[i] += w[i][j];
			}
		}

		for (int j = 0; j < m; j++)
		{

			for (int i = 0; i < m; i++)
			{
				D[j] += w[i][j];
			}
		}



		IloArray<IloNumVarArray>z(env, m);

		for (int i = 0; i < m; i++)
		{
			z[i] = IloNumVarArray(env, m, 0, 1, ILOBOOL);
		}

		//y 3d matrica
		IloArray<IloArray<IloNumVarArray>> y(env, m);
		for (int i = 0; i < m; i++)
		{
			y[i] = IloArray<IloNumVarArray>(env, m);

			for (int j = 0; j < m; j++)
			{
				y[i][j] = IloNumVarArray(env, m, 0, INFINITY, ILOFLOAT);
			}
		}

		IloExpr fc(env);

		for (int i = 0; i < m; i++)
		{
			for (int k = 0; k < m; k++)
			{
				fc += c[i][k] * z[i][k] * (lambda * O[i] + delta * D[i]);
			}
		}

		for (int i = 0; i < m; i++)
		{
			for (int k = 0; k < m; k++)
			{
				for (int l = 0; l < m; l++)
				{
					fc += alpha * c[k][l] * y[i][k][l];
				}
			}

		}

		for (int i = 0; i < m; i++)
		{
			fc += z[i][i] * f[i];
		}
		model.add(IloMinimize(env, fc));
		for (int i = 0; i < m; i++)
		{
			IloExpr cond1(env);
			for (int k = 0; k < m; k++)
			{
				cond1 += z[i][k];
			}
			model.add(cond1 == 1);
			cond1.end();
		}

		for (int i = 0; i < m; i++)
		{
			for (int k = 0; k < m; k++)
			{
				IloExpr cond2(env);
				cond2 = z[i][k] - z[k][k];
				model.add(cond2 <= 0);
				cond2.end();
			}
		}

		for (int i = 0; i < m; i++)
		{
			for (int k = 0; k < m; k++)
			{
				IloExpr cond3(env);
				for (int j = 0; j < m; j++)
				{
					cond3 += w[i][j] * z[j][k] + y[i][k][j] - y[i][j][k];
				}
				cond3 -= O[i] * z[i][k];
				model.add(cond3 == 0);
				cond3.end();

			}
		}
		IloCplex cplex(model);
		cplex.setOut(env.getNullStream());
		if (!cplex.solve())
			cout << "Nije moguce resiti.";

		else
		{
			cout << "Vrednost f-je cilja:" << cplex.getObjValue() << endl;
			cout << "Status: " << cplex.getStatus() << endl;
			cout << "Vreme: " << cplex.getTime() << endl;

		}

	}
	catch (IloException& ex) {
		cerr << "Desila se greska: " << ex << endl;
	
	}
}
	







