Определение k-максимальных элементов
Для каждого БО определим 1-, 2-, 3-, 4-максимальные элементы.
При этом рассматриваются множества подчиненных, эквивалентных и несравнимых элементов. Специфика для определенных выше бинарных отношений заключается в том, что эквивалентным для каждого элемента является только он сам, а несравнимые с ним элементы как правило равнозначны. Поэтому 2- и 3-максимальных элементов получаем не 1, а множество, так как имеем несколько элементов, S-множества которых одной размерности, но разные по составу, то есть все эти элементы удовлетворяют определению k-максимальности. Этой же причиной объясняется отсутствие 1- и 4- максимальных элемента для тех БО, где несколько лидеров (они имеют одинаковые S-множества, то есть ни один не удовлетворяет определению k-максимальности).
Для каждого БО имеем k-максимальные элементы:
№ | Бинарное отношение | 1-max | 2-max | 3-max | 4-max | |
Общая площадь | G | G | G | G | ||
Цена | C | C | C | C | ||
Удаленность от метро | - | D F | D F | - | ||
Район | F | F | F | F | ||
Дом | G | G | G | G | ||
Состояние квартиры | - | E G | E G | - | ||
Размер кухни | G | G | G | G | ||
Этаж | - | A B D F G I J | A B D F G I J | - | ||
Наличие балкона | A | A | A | A | ||
Экология | G | G | G | G |
Аналогично вышеописанным действиям, можно выбрать наилучший элемент с учетом весов признаков. Лучшим является вариант решения G.
Вывод
Таким образом, по всем рассматриваемым критериям оптимальным является вариант G:
Sкварт | Цена, у.е. | До метро | Район | Дом | Состояние квартиры | Sкухни | Этаж | Балкон | Экология | |
G, ул. Фрунзе, 6 | 5 мин пешком | Московский | Кирпич после кап. ремонта | Отличное | Лоджия | Рядом Парк Победы, отличная |
Программа
#include "stdio.h"
#include "math.h"
#include "conio.h"
//число критериев (бинарных отношений)
#define DIM 10
//число вариантов решения
#define ITEM_NUMBER 10
float weight[] = {0.15f, 0.3f, 0.1f, 0.05f, 0.1f, 0.15f, 0.05f, 0.03f, 0.02f, 0.05f};
//класс для матрицы, задающей каждое из бинарных отношений
class Matrix
{
int data[ITEM_NUMBER][ITEM_NUMBER];
public:
Matrix(){}
void SetElement(int i, int j, int value)
{
if ((i>ITEM_NUMBER) || (j>ITEM_NUMBER)) return;
data[i][j] = value;
}
int H_Enum(int *vector, int i)
{
int n = 0;
for (int j = 0; j < ITEM_NUMBER; j++)
{
if (i==j) continue;
//xRy and yNotRx
if ((data[i][j] == 1) && (data[j][i] == 0))
{
vector[n] = j;
n++;
}
}
return n;
}
int E_Enum(int *vector, int i)
{
int n = 0;
for (int j = 0; j < ITEM_NUMBER; j++)
{
//xRy and yRx
if (((data[i][j] == 1) && (data[j][i] == 1)) || (i == j))
{
vector[n] = j;
n++;
}
}
return n;
}
int N_Enum(int *vector, int i)
{
int n = 0;
for (int j = 0; j < ITEM_NUMBER; j++)
{
if (i==j) continue;
//xNotRy and yNotRx
if ((data[i][j] == 0) && (data[j][i] == 0))
{
vector[n] = j;
n++;
}
}
return n;
}
//считается, что множества упорядочены (это получается по построению,
//и объединение не нарушает порядка)
int UnionEnums(int *vector1, int *vector2, int n1, int n2, int *result)
{
int i,j,k;
i = 0; j = 0; k = 0;
bool ready = false;
while (!ready)
{
if ((i < n1) && (j < n2))
{
if (vector1[i] < vector2[j])
{
result[k] = vector1[i];
i++;
k++;
}
else
{
result[k] = vector2[j];
j++;
k++;
}
}
else if ((i < n1) || (j < n2))
{
if (i < n1)
{
while(i < n1)
{
result[k] = vector1[i];
i++;
k++;
}
ready = true;
}
if (j < n2)
{
while(j < n2)
{
result[k] = vector2[j];
j++;
k++;
}
ready = true;
}
}
else
{
ready = true;
}
}
return k;
}
//если равны или если vector1 содержится в vector2, то 1, в остальных случаях 0.
//Мн-ва д.б. упорядочены
int CompareEnums(int *vector1, int *vector2, int n1, int n2)
{
int i,j;
if (n1 > n2) return 0;//т.к. 1 должен сожердаться в 2, его размер д.б. меньше
if (n1 == n2)//проверить на равенство
{
for (i = 0; i < n1; i++)
{
if (vector1[i] != vector2[i])
{
return 0;
}
}
return 1;//раз досюда дошли, точно равенство
}
else//n1<n2
{
j = 0;
for(i = 0; i < n1; i++)
{
while ((vector1[i] != vector2[j]) && (j < n2)) j++;
if (j == n2) return 0;//не нашли подходящего элемента
//в противном случае нашли и все ок, идем дальше
}
}
return 1;
}
//Получить варианты решения по механизму доминирования
int Dominate(int *vector)
{
int i,j;
int n = 0;
for (i = 0; i < ITEM_NUMBER; i++)
{
bool dominate = true;
for (j = 0; j < ITEM_NUMBER; j++)
{
if (i==j)
continue;//диагональные элементы не проверяем
//если от него ко всем есть стрелки, то 1 д.б. во всей строчке (кроме i,i)
if (data[i][j] == 0)
{
dominate = false;
break;
}
}
if(dominate)
{
vector[n] = i;
n++;
}
}
return n;
}
//Получить варианты решения по механизму блокировки
int Block(int *vector)
{
int i,j;
int n = 0;
for (j = 0; j < ITEM_NUMBER; j++)
{
bool block = true;
for (i = 0; i < ITEM_NUMBER; i++)
{
if (i==j)
continue;//диагональные элементы не проверяем
//если к нему ни от кого нет стрелок, то 0 д.б. во всем столбце(кроме i,i)
if (data[i][j] == 1)
{
block = false;
break;
}
}
if(block)
{
vector[n] = j;
n++;
}
}
return n;
}
//получить варианты по турнирному механизму (fR(x) для каждого варианта)
void Tournament(float *vector)
{
int i,j;
for (i = 0; i < ITEM_NUMBER; i++)
{
vector[i] = 0;
for(j = 0; j < ITEM_NUMBER; j++)
{
if (i == j)
continue;
if ((data[i][j] == 1) && (data[j][i] == 0))
{
vector[i] += 1;
}
else if ((data[i][j] == 0) && (data[j][i] == 1))
{
vector[i] += 0;//ну типа для порядка
}
else
{
vector[i] += 0.5f;
}
}
}
}
void Print()
{
printf("\n");
for(int i = 0; i < ITEM_NUMBER; i++)
{
for(int j=0; j < ITEM_NUMBER; j++)
{
printf("%2d ",data[i][j]);
}
printf("\n");
}
}
};
void main()
{
int i,j,k;
Matrix System[DIM];
/***************************************************************************************/
FILE * inFile;
inFile = fopen("data.txt", "r");
for(k = 0; k < DIM; k++)
{
fscanf(inFile, "\n");//заголовок матрицы
for (i = 0; i < ITEM_NUMBER; i++)
{
for(j = 0; j < ITEM_NUMBER; j++)
{
int d;
fscanf(inFile, "%d",&d);
System[k].SetElement(i,j,d);
}
}
//printf("\nMatrix #%1d",k+1);
//System[k].Print();
}
fclose(inFile);
/**********************************************************************************/
printf("Dominating\n========================================================");
for(k = 0; k < DIM; k++)
{
int dominatingElement[ITEM_NUMBER];
int count = System[k].Dominate(dominatingElement);
printf("\nR #%d: ", k);
for(i = 0; i < count; i++)
{
printf("%c ", 65+dominatingElement[i]);
}
}
/*************************************************************************************/
printf("\n\nBlocking\n=========================================================");
for(k = 0; k < DIM; k++)
{
int blockingElement[ITEM_NUMBER];
int count = System[k].Block(blockingElement);
printf("\nR #%d: ", k);
for(i = 0; i < count; i++)
{
printf("%c ", 65+blockingElement[i]);
}
}
/***************************************************************************************/
printf("\n\nTournament\n========================================================");
float placesSum[ITEM_NUMBER];
for(k = 0; k < ITEM_NUMBER; k++)
{
placesSum[k] = 0;
}
for(k = 0; k < DIM; k++)
{
float tournamentRes[ITEM_NUMBER];
int systems[ITEM_NUMBER];
for (i = 0; i < ITEM_NUMBER; i++)
systems[i] = i;
System[k].Tournament(tournamentRes);
//sort
bool sorted = false;
while (!sorted)
{
sorted = true;
for(i = 0; i < ITEM_NUMBER-1; i++)
{
if (tournamentRes[i] < tournamentRes[i+1])
{
sorted = false;
float tr = tournamentRes[i];
tournamentRes[i] = tournamentRes[i+1];
tournamentRes[i+1] = tr;
int pl = systems[i];
systems[i] = systems[i+1];
systems[i+1] = pl;
}
}
}
//(места считаются с 1-ого, а не с нулевого)
int curPlace = 0;
int deltaPlace = 1;
float lastValue = -1;
//printf("\n\n-----------------\nR #%d\n", k);
for(i = 0; i < ITEM_NUMBER; i++)
{
//printf("%c %4.2f\n", systems[i]+65, tournamentRes[i]);
if (tournamentRes[i] == lastValue)
{
deltaPlace++;
}
else
{
lastValue = tournamentRes[i];
curPlace += deltaPlace;
deltaPlace = 1;
}
placesSum[systems[i]] += weight[k] * curPlace;
}
}
//sort Summary list and print it
int systems[ITEM_NUMBER];
for (i = 0; i < ITEM_NUMBER; i++)
systems[i] = i;
bool sorted = false;
while (!sorted)
{
sorted = true;
for(i = 0; i < ITEM_NUMBER-1; i++)
{
if (placesSum[i] > placesSum[i+1])
{
sorted = false;
float ps = placesSum[i];
placesSum[i] = placesSum[i+1];
placesSum[i+1] = ps;
int pl = systems[i];
systems[i] = systems[i+1];
systems[i+1] = pl;
}
}
}
//printf("\n\n-----------------\nTournament Summary");
printf("\n");
for(i = 0; i < ITEM_NUMBER; i++)
{
printf("%c %4.2f\n", systems[i]+65, placesSum[i]);
}
/**************************************************************************************/
printf("\n\n1 MAXIMUM\n========================================================");
for(k = 0; k < DIM; k++)
{
int kMax = 0;
int Max[ITEM_NUMBER];
//printf("\n\n-----------------");
printf("\nR #%d: ", k);
//каждый проверяем на возможность быть k-максимальным
for (i = 0; i < ITEM_NUMBER; i++)
{
int maxHNE[ITEM_NUMBER];
int maxHNEcount;
int H[ITEM_NUMBER];
int E[ITEM_NUMBER];
int N[ITEM_NUMBER];
int HN[ITEM_NUMBER];
int HNE[ITEM_NUMBER];
int countH, countE, countN, countHN, countHNE;
//получим нужную характеристику для рассматриваемого элемента
countH = System[k].H_Enum(H, i);
countN = System[k].N_Enum(N, i);
countE = System[k].E_Enum(E, i);
countHN = System[k].UnionEnums(N, H, countN, countH, HN);
maxHNEcount = System[k].UnionEnums(E, HN, countE, countHN, maxHNE);
bool valid = true;
//проверяем по остальным элементам
for (j = 0; j < ITEM_NUMBER; j++)
{
if (i == j) continue;
countH = System[k].H_Enum(H, j);
countN = System[k].N_Enum(N, j);
countE = System[k].E_Enum(E, j);
countHN = System[k].UnionEnums(N, H, countN, countH, HN);
countHNE = System[k].UnionEnums(E, HN, countE, countHN, HNE);
//если есть такой элемент, что maxS в его S, то i - не k-max
if(System[k].CompareEnums(maxHNE, HNE, maxHNEcount, countHNE))
{
valid = false;
break;
}
}
if (valid)
{
Max[kMax] = i;
kMax++;
}
}
if (kMax)
{
for(i = 0; i < kMax; i++)
{
printf(" %c", Max[i]+65);
}
}
else
{
printf(" No 1 MAX");
}
}
/***************************************************************************************/
printf("\n\n2 MAXIMUM\n=======================================================");
for(k = 0; k < DIM; k++)
{
int kMax = 0;
int Max[ITEM_NUMBER];
//printf("\n\n-----------------");
printf("\nR #%d: ", k);
int l = -1;
//каждый проверяем на возможность быть k-максимальным
for (i = 0; i < ITEM_NUMBER; i++)
{
int maxHN[ITEM_NUMBER];
int maxHNcount;
int H[ITEM_NUMBER];
int N[ITEM_NUMBER];
int HN[ITEM_NUMBER];
int countH, countN, countHN;
//получим нужную характеристику для рассматриваемого элемента
countH = System[k].H_Enum(H, i);
countN = System[k].N_Enum(N, i);
maxHNcount = System[k].UnionEnums(N, H, countN, countH, maxHN);
bool valid = true;
//проверяем по остальным элементам
for (j = 0; j < ITEM_NUMBER; j++)
{
if (i == j) continue;
countH = System[k].H_Enum(H, j);
countN = System[k].N_Enum(N, j);
countHN = System[k].UnionEnums(N, H, countN, countH, HN);
//если есть такой элемент, что maxS в его S, то i - не k-max
if(System[k].CompareEnums(maxHN, HN, maxHNcount, countHN))
{
valid = false;
break;
}
}
if (valid)
{
Max[kMax] = i;
kMax++;
}
}
if (kMax)
{
for(i = 0; i < kMax; i++)
{
printf(" %c", Max[i]+65);
}
}
else
{
printf(" No 2 MAX");
}
}
/***************************************************************************************/
printf("\n\n3 MAXIMUM\n====================================================");
for(k = 0; k < DIM; k++)
{
int kMax = 0;
int Max[ITEM_NUMBER];
//printf("\n\n-----------------");
printf("\nR #%d: ", k);
//каждый проверяем на возможность быть k-максимальным
for (i = 0; i < ITEM_NUMBER; i++)
{
int maxHE[ITEM_NUMBER];
int maxHEcount;
int H[ITEM_NUMBER];
int E[ITEM_NUMBER];
int HE[ITEM_NUMBER];
int countH, countE, countHE;
//получим нужную характеристику для рассматриваемого элемента
countH = System[k].H_Enum(H, i);
countE = System[k].E_Enum(E, i);
maxHEcount = System[k].UnionEnums(E, H, countE, countH, maxHE);
bool valid = true;
//проверяем по остальным элементам
for (j = 0; j < ITEM_NUMBER; j++)
{
if (i == j) continue;
countH = System[k].H_Enum(H, j);
countE = System[k].E_Enum(E, j);
countHE = System[k].UnionEnums(E, H, countE, countH, HE);
//если есть такой элемент, что maxS в его S, то i - не k-max
if(System[k].CompareEnums(maxHE, HE, maxHEcount, countHE))
{
valid = false;
break;
}
}
if (valid)
{
Max[kMax] = i;
kMax++;
}
}
if (kMax)
{
for(i = 0; i < kMax; i++)
{
printf(" %c", Max[i]+65);
}
}
else
{
printf(" No 3 MAX");
}
}
/***************************************************************************************/
printf("\n\n4 MAXIMUM\n==================================================");
for(k = 0; k < DIM; k++)
{
int kMax = 0;
int Max[ITEM_NUMBER];
//printf("\n\n-----------------");
printf("\nR #%d: ", k);
//каждый проверяем на возможность быть k-максимальным
for (i = 0; i < ITEM_NUMBER; i++)
{
int maxH[ITEM_NUMBER];
int maxHcount;
int H[ITEM_NUMBER];
int countH;
//получим нужную характеристику для рассматриваемого элемента
maxHcount = System[k].H_Enum(maxH, i);
bool valid = true;
//проверяем по остальным элементам
for (j = 0; j < ITEM_NUMBER; j++)
{
if (i == j) continue;
countH = System[k].H_Enum(H, j);
//если есть такой элемент, что maxS в его S, то i - не k-max
if(System[k].CompareEnums(maxH, H, maxHcount, countH))
{
valid = false;
break;
}
}
if (valid)
{
Max[kMax] = i;
kMax++;
}
}
if (kMax)
{
for(i = 0; i < kMax; i++)
{
printf(" %c", Max[i]+65);
}
}
else
{
printf(" No 4 MAX");
}
}
getch();
}