русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Программная реализация метода решения транспортной задачи


Дата добавления: 2015-01-16; просмотров: 1221; Нарушение авторских прав


//файл включения для векторных и матричных объектов

#include <winsys\geometry.h>

#include <classlib\arrays.h>

#include <values.h>

#pragma hdrstop

#include "matrix.h"

 

/*определяем типы "действительная матрица" и "действительный вектор"*/

typedef matrix<double> dmatrix;

typedef vector<double> dvector;

//определяем тип "массив точек"

typedef TArray<TPoint> Array;

 

 

/*набор функций, проверяющих, возможно ли движение в заданном направлении, то есть имеется ли в заданном направлении базисная ячейка*/

TPoint up(dmatrix x,TPoint cur)

{

for(long i=cur.X()-1;i>=0;i--)

if(x[i][cur.Y()]>0)/*если есть пункт, в который можно передвинуться*/

return TPoint(i,cur.Y());/*возвращаем его координаты*/

return TPoint(-1,-1);/*если не нашли - возвращаем признак ошибки*/

}

 

 

TPoint down(dmatrix x,TPoint cur)

{

for(long i=cur.X()+1;i<x.getm();i++)

if(x[i][cur.Y()]>0)

return TPoint(i,cur.Y());

return TPoint(-1,-1);

}

 

 

TPoint left(dmatrix x,TPoint cur)

{

for(long i=cur.Y()-1;i>=0;i--)

if(x[cur.X()][i]>0)

return TPoint(cur.X(),i);

return TPoint(-1,-1);

}

 

 

TPoint right(dmatrix x,TPoint cur)

{

for(long i=cur.Y()+1;i<x.getn();i++)

if(x[cur.X()][i]>0)

return TPoint(cur.X(),i);

return TPoint(-1,-1);

}

 

 

/*эта функция проверяет, есть ли пункт в заданном массиве – цикле*/

long exist(Array way,TPoint newpoint)

{

/*дополнительно проверяем координаты пункта на корректность*/

if(newpoint==TPoint(-1,-1))

return 1;

for(long i=0;i<way.GetItemsInContainer();i++)

if(way[i]==newpoint)

return 1;

return 0;

}

 

 

/*функция, определяющая, лежат ли три точки в одной строке (столбце)*/



inline long OnOneLine(TPoint p1, TPoint p2, TPoint p3)

{

return (p1.X()==p2.X()&&p1.X()==p3.X())||

(p1.Y()== p2.Y()&&p1.Y()==p3.Y());

}

 

 

/*часто повторяющиеся действия можно реализовать не только в виде функций, но и, к примеру, в виде макро. Например:

- в этом фрагменте проверяется, превышает ли число неудачных (тупиковых) попыток продвинуться в одном из четырёх возможных направлений количество этих направлений. Если это так, то пункт, из которого мы пытаемся пройти дальше, объявляется тупиковым (помечается нулём), затем изымается из массива пунктов цикла - пути перевозки груза, общее количество пунктов перевозки уменьшается на единицу и количество неудачных попыток объявляется нулевым*/

#define otkat if(tupik>4)\

{\

x[way[i].X()][way[i].Y()]=0;\

way.Detach(i);\

i--;\

tupik=0;\

}

/*- этот фрагмент выполняются после того, как определен следующий пункт, куда можно перевезти груз. При этом вначале количество неудачных попыток увеличивается на единицу - а вдруг идти в этот пункт нельзя? Затем выполняется проверка координат пункта на допустимость и наличие пункта в цикле (не провозили ли мы уже здесь груз в текущем цикле перевозок). Если всё Ок, пункт добавляется в цикл перевозок, количество неудачных попыток устанавливается в ноль, а количество пунктов перевозки в цикле увеличивается. Если же из текущей точки можно перейти в начальную, то цикл перевозок считается замкнутым и поиск новых пунктов можно прервать*/

#define addpoint tupik++;\

if(!exist(way,newpoint))\

{\

way.Add(newpoint);\

tupik=0;\

i++;\

if(i!=1&&(newpoint.X()==pq.X()\

||newpoint.Y()==pq.Y()))\

break;\

}

 

 

/*эта функция в заданной матрице перевозок ищет цикл, соответствующий перевозке из заданной точки*/

Array findway(dmatrix x, TPoint pq)

{

/*Вычёркивание тех пунктов, которые могут завести в тупик. Для этой цели вычёркиваем из матрицы все ряды, кроме строки p и столбца q, имеющие не более одной базисной клетки. Этот процесс повторяем до тех пор, пока есть что вычёркивать*/

for(long count=0,flag=1;flag;)

{

flag=0;/*вначале считаем, что вычёркивать нечего*/

for(long i=0;i<x.getm();i++)

if(i!=pq.X())

{

for(long j=count=0;j<x.getn();j++)

if(x[i][j]>0)

count++;

//если в строке только одна базисная клетка

if(count<2&&count)

{

flag=1;//взводим флаг вычёркивания

for(long j=0;j<x.getn();j++)

x[i][j]=0;//обнуляем текущую строку

}

}

//ту же операцию проводим со столбцами

for(long j=0;j<x.getn();j++)

if(j!=pq.Y())

{

for(long i=count=0;i<x.getm();i++)

if(x[i][j]>0)

count++;

if(count<2&&count)

{

flag=1;

for(long i=0;i<x.getm();i++)

x[i][j]=0;

}

}

}

 

long tupik=0;//количество тупиков обнуляем

/*объявляем массив для хранения координат пунктов, участвующих в цикле перевозок*/

Array way(0,0,20);

/*добавляем в массив первый (несуществующий пункт)*/

way.Add(pq);

for(long i=0;;)

{

/*пытаемся двигаться в различных направлениях так, чтобы составить цикл*/

otkat

TPoint newpoint=down(x,way[i]);

addpoint

else

{

otkat

newpoint=up(x,way[i]);

addpoint

}

otkat

newpoint=left(x,way[i]);

addpoint

else

{

otkat

newpoint=right(x,way[i]);

addpoint

}

}

/*если в цикле три точки лежат в одном ряду, вычёркиваем среднюю*/

for(long i=0;i<way.GetItemsInContainer()-2;i++)

if(OnOneLine(way[i],way[i+1],way[i+2]))

way.Detach(i+1);

return way;/*возвращаем цикл перевозок для данной точки*/

}

 

 

/*составляем матрицу методом "северо-западного угла", распределяя запасы а в соответствии с заявками b*/

dmatrix transp_getopor(dvector a, dvector b)

{

dmatrix x(a.getm(),b.getm());

for(long j=0,i=0;j<b.getm();)

{

if(a[i]>=b[j])//если запасы превышают заявки

{

x[i][j]=b[j];//удовлетворяем заявки

a[i]-=b[j]; //уменьшаем запасы

j++;/*переходим к обслуживанию следующей заявки*/

}

else//иначе

{

x[i][j]=a[i];/*удовлетворяем, сколько есть запасов*/

b[j]-=a[i]; //уменьшаем количество заявок

i++; //переходим к следующему запасу

}

}

return x;//возвращаем опорное решение

}

 

 

//передвижение груза по циклу в матрице перевозок

void movegruz(dmatrix &x,Array way)

{

/*определяем пункт с минимальной ценой в отрицательных вершинах цикла*/

double _min=x[way[1].X()][way[1].Y()];

for(long i=3;i<way.GetItemsInContainer();i++)

if(x[way[i].X()][way[i].Y()]<_min)

_min=x[way[i].X()][way[i].Y()];

/*в положительных вершинах количество груза увеличиваем, в отрицательных – уменьшаем*/

for(long i=0;i<way.GetItemsInContainer();i+=2)

x[way[i].X()][way[i].Y()]+=_min;

for(long i=1;i<way.GetItemsInContainer();i+=2)

x[way[i].X()][way[i].Y()]-=_min;

}

 

 

//определяем цену цикла

double getprice(dmatrix c,Array way)

{

double price=0;

/*положительные вершины прибавляем, отрицательные – вычитаем*/

for(long i=0;i<way.GetItemsInContainer();i+=2)

price+=c[way[i].X()][way[i].Y()];

for(long i=1;i<way.GetItemsInContainer();i+=2)

price-=c[way[i].X()][way[i].Y()];

return price;//возвращаем цену цикла

}

 

 

/*поиск оптимальной (минимизирующей стоимость) перевозки; возвращаемое значение - матрица, первые два столбца в которой указывают номер склада (от 0) и номер пункта назначения (тоже от 0), а последний - количество перевозимого груза ("из первого столбца во второй")*/

dmatrix transp_optim(dmatrix &x, dmatrix c)

{

long i,j,count;

for(i=0;i<x.getm();i++)

for(j=0;j<x.getn();j++)

if(!x[i][j])//если текущая ячейка пустая

{

Array way=findway(x,TPoint(i,j));/*ищем для неё цикл перевозки*/

if(getprice(c,way)<0)/*если найденный цикл имеет отрицательную цену, то мы можем улучшить положение дел,*/

{

movegruz(x,way);//перевезя по нему груз

j=x.getn();/*перезапускаем после перевозки цикл просмотра пустых ячеек*/

i=-1;

}

}

//подсчитываем количество перевозок

for(i=count=0;i<x.getm();i++)

for(j=0;j<x.getn();j++)

if(x[i][j])

count++;

dmatrix res(count,3);/*создаём матрицу, в которую заносим направление перевозки и количество груза*/

for(i=count=0;i<x.getm();i++)

for(j=0;j<x.getn();j++)

if(x[i][j])

res[count][0]=i, res[count][1]=j,

res[count][2]=x[i][j], count++;

return res;//возвращаем план перевозок

}

 

 

/*решение транспортной задачи. Эта функция принимает матрицу стоимости и вектора запасов и заявок (а и b)*/

dmatrix transp(dmatrix c, dvector a, dvector b)

{

//проверка входных параметров на корректность

if(c.getm()!=a.getm())

throw xmsg("Некорректные входные параметры");

if(c.getn()!=b.getm())

throw xmsg("Некорректные входные параметры");

double sum1=0,sum2=0;

for(long i=0;i<a.getm();sum1+=a[i++]);

for(long i=0;i<b.getm();sum2+=b[i++]);

if(sum1!=sum2)

throw xmsg("Некорректные входные параметры");

dmatrix x=transp_getopor(a,b);/*поиск опорного решения*/

return transp_optim(x,c); //оптимизация решения

}

 

 

//Тест

void main()

{

double mtr[]=//матрица стоимости

{

10,7,6,8,

5,6,5,4,

8,7,6,7

};

double vec1[]={31,48,38};//запасы

double vec2[]={22,34,41,20};//заявки

dmatrix c(3,4,mtr), a(3,vec1), b(4,vec2);

dmatrix res=transp(c,a,b);

cout<<res<<endl;

double L=0;

//подсчитываем цену перевозки

for(long i=0,count=0;i<c.getm()&&

count<res.getm();i++)

for(long j=0;j<c.getn()&&count<res.getm();j++)

if(i==res[count][0]&&j==res[count][1])

L+=c[i][j]*res[count][2],

count++;

cout<<"L="<<L<<endl;

}



<== предыдущая лекция | следующая лекция ==>
Симплекс-метод решения ОЗЛП | Общая постановка задачи


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 1.37 сек.