Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
alg_wpor.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
391.77 Кб
Скачать

1. Беллман-Форд алгоритмімен шешілетін есепке сипаттама беріңіз. Алгоритмді қолданып жалпылама мысал келтіріңіз.

Алгоритмнің тарихы бірден үш тәуелсіз математиктермен байланысты болып табылады: Лестер Фордпен, Ричард Беллманмен және Эдвард Мурмен. Форд және Беллман алгоритмді сәйкесінше 1956 және 1958 жыдары, ал Мур 1957 жылы жариялаған. Сондықтан кейде оны Беллман – Форд – Мур алгоритмі деп атайды. Әдіс дистанциялық-векторлық маршрутизацияның кейбір протоколдарында, мысалы RIP (Routing Information Protocol – Маршруттық ақпарат протоколында) қолданылады.

Дейкстр алгоритмы сияқты Беллман-Форд алгоритмі взвешенныйграфтағы бір шыңнан басқаларына дейінгі ең қысқа жолдарын есептейді. Ол кері весы бар қабырғалары бар графтармен жұмыс жүргізу үшін ыңғайлы болып табылады. Дегенмен, алгоритмді қолдану шектері осындай графтардың барлығын қамтымайды, себебі вестарыныңқосындысыкері болып табылатын (яғни кері цикл бойынша) қабырғалардан құрастырылған жолмен әр бір кезекті өту қажетті мәнде тек жақсарта түседі. Жақсартулардың шексіз саны оптималды болып табылатын бір нақты мәннің анықталуын мүмкін емес етеді. Осыған байланысты Беллман-Форд алгоритмін кері циклдары бар графтар үшін қолдану мүмкін емес, бірақ ол сондай графтарды анықтауға мүмкінік береді.

Есепті шешу, яғни Беллман-Форд алгоритмін қолдана отырып sшыңынанбарлық қалғандарына дейінгі ең қысқа жолдарды табудинамикалық бағдарламалау әдісін қолдануды білдіреді: оны типтік кіші есептерге бөлу, олардың шешуін табу, сол арқылы негізгі есепті шығару. Мұнда осындай кіші есептердің шешуі ретінде жеке алынған қабырғадан басқасына дейінгі ең жақсы жолын анықтау болады.

Алгоритм жұмысының нәтижелерін сақтау үшін бір өлшемді d[]массивін жасаймыз. Оның әр бір d[i] элементінде sшыңынанiшыңына дейінгі (ондай бар болатын болса) ең қысқа жолдың мәні сақталатын болады. Алдымен d[] массивының элементтеріне шартты шексіздікке тең болатын мәндерді береміз (мысалы, барлық вестардың қосындысынан алдын ала көп болатын санды), ал d[s] элементін нольге теңдестіреміз. Осылайша біз мәлім және қажетті ақпаратты іске қосамыз, атап айтқанда sшыңынандәл оның өзіне дейінгі ең жақсы жол нольге тең екендігі белгілі, және басқа шыңдарға s-танқол жеткізудің мүмкін еместігін қарастырамыз. Алгоритмді орындау барысында олардың кейбіреулері үшін бұл шарт жалған болып шығады, және sшыңынан осы шыңдарға дейінгі жолдардың оптималды құндары есептелінеді.

G=(V, E) графы бар деп ұйғарайық және n=|V|, ал m=|E|. Бұл графтың сәйкес келетін шыңдарын v және u (v∈V и u∈V) символдарымен, ал (v, u) қабырғасының весынwсимволымен белгілейміз. Басқаша айтқанда,  v шыңынан шығып, uшыңына кіретін қабырғаның весыw-ға тең болады. Онда Беллман-Форд алгоритмі келесі түрге келеді:

1-ден n-1-ге дейінгі i үшін орындау

1-ден m-ге дейінгі j үшін орындау

Егер d[v] + w(v, u) < d[u] онда d[u] < d[v] + w(v, u)

Әр бір nкезеңіндеd[] массивы элементтерінің мәнін жақсарту әрекеттері іске асырылады, егер w(v, u) қабырғасының весы мен d[v]элементінде сақталатын вестыңқосындысыd[u]весынан төмен болатын болса, ол соңғысына жатқызылады. C++ тағы бағдарлама коды:

#include "stdafx.h" #include <iostream> #define inf 100000 using namespace std; struct Edges{ int u, v, w; }; const int Vmax=1000; const int Emax=Vmax*(Vmax-1)/2; int i, j, n, e, start; Edges edge[Emax]; int d[Vmax]; //алгоритмБеллмана-Форда void bellman_ford(int n, int s) { int i, j; for (i=0; i<n; i++) d[i]=inf; d[s]=0; for (i=0; i<n-1; i++) for (j=0; j<e; j++) if (d[edge[j].v]+edge[j].w<d[edge[j].u]) d[edge[j].u]=d[edge[j].v]+edge[j].w; for (i=0; i<n; i++) if (d[i]==inf) cout<<endl<<start<<"->"<<i+1<<"="<<"Not"; else cout<<endl<<start<<"->"<<i+1<<"="<<d[i]; } //главнаяфункция

void main() { setlocale(LC_ALL, "Rus"); int w; cout<<"Количествовершин> "; cin>>n; e=0; for (i=0; i<n; i++) for (j=0; j<n; j++) { cout<<"Вес "<<i+1<<"->"<<j+1<<" > "; cin>>w; if (w!=0) { edge[e].v=i; edge[e].u=j; edge[e].w=w; e++; } } cout<<"Стартоваявершина> "; cin>>start; cout<<"Списоккратчайшихпутей:"; bellman_ford(n, start-1); system("pause>>void"); }

Мұнда граф вестардың матрицасын пайдаланушы енгізу барысында қалыптасатын қабырғалардың жеңілдетілген тізімімен көрсетілген. Беллман-Форд алгоритмінің негізгі бөлігі (шартты тексеру) m*(n-1)рет орындалады, себебі сыртқы циклдың қайталану саны n-1-ге тең, ал ішкі циклдың қайталану саны m-ге тең.n-дық итерациядан бас тарту дұрыс, өйткені алгоритм өз міндетін n-1 кезеңінде орындайды, ал сыртқы циклды nрет қосу графтағы кері циклдың бар болуын айқындауға мүмкіндік береді. Оны келесі модификация арқылы тексеруге болады:

bool x=true; for (i=0; i<n; i++) { if (i!=n-1) for (j=0; j<e; j++) if (d[edge[j].v]+edge[j].w<d[edge[j].u]) d[edge[j].u]=d[edge[j].v]+edge[j].w; if (i==n-1) for (j=0; j<e; j++) if (d[edge[j].v]+edge[j].w<d[edge[j].u]) x=false; } if (!x) cout<<endl<<"Графсодержитотриц. циклы"<<endl;

Мұнда сыртқы цикл nрет орындалады (C++ те алдымен 0 мәнін көрсету қабылданған, сондықтан берілген код үшін n-1рет), және егер n-ші кезеңде жақсарту мүмкін болса, ол кері циклдың бар екендігін дәлелдейді.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]