#include <stdio.h>
#include <stdbool.h>
#define N (7) /* 地点の数 */
/* 地点間距離 */
/* ※1 地点aと地点bが同一の地点の場合は0が格納されている */
/* ※2 地点aと地点bが隣接地点でない場合は-1が格納されている */
/*static*/ int DISTANCE_MAP[N][N] = {
/*a ->b 0 1 2 3 4 5 6 */
/*0*/ {+0, +2, +8, +4, -1, -1, -1},
/*1*/ {+2, +0, -1, -1, +3, -1, -1},
/*2*/ {+8, -1, +0, -1, +2, +3, -1},
/*3*/ {+4, -1, -1, +0, -1, +8, -1},
/*4*/ {-1, +3, +2, -1, +0, -1, +9},
/*5*/ {-1, -1, +3, +8, -1, +0, +3},
/*6*/ {-1, -1, -1, -1, +9, +3, +0},
};
typedef const char *String;
typedef int Point;
typedef int Distance;
#define Distance_MAX (99999)
typedef struct route
{
Point start, destination;
Distance distance;
Point point[N];
} Route;
void find_shortest(Route *route)
{
Point point;
Distance distance, shortest_distance[N];
bool fixed[N];
/* 初期化 */
for (point = 0; point < N; point++)
{
shortest_distance[point] = Distance_MAX;
fixed[point] = false;
}
shortest_distance[route->start] = 0;
while (true)
{
/* 未確定地点を1つ探す */
for (point = 0; point < N && fixed[point]; point++)
{
}
if (point == N)
return;
/* 最短距離がより短い地点を探す */
for (int i = point + 1; i < N; i++)
{
if (!fixed[i] && shortest_distance[i] < shortest_distance[point])
{
point = i;
}
}
fixed[point] = true;
/* 距離再計算 */
for (int i = 0; i < N; i++)
{
if (fixed[i])
{
continue;
}
distance = DISTANCE_MAP[point][i];
if (distance <= 0)
{
continue;
}
distance += shortest_distance[point];
if (distance < shortest_distance[i])
{
shortest_distance[i] = distance;
route->point[i] = point;
}
}
route->distance = shortest_distance[route->destination];
}
}
void print_route(Route *route, Point destination)
{
/* 目的地から出発地までの経路を逆順にたどって出発地から表示する */
if (route->start == destination)
{
}
else
{
print_route(route, route->point[destination]);
printf(" -> %d", destination
); }
}
void print_shortest(Route *route)
{
print_route(route, route->destination);
printf("\n出発地から目的地までの最短距離 = %d\n", route
->distance
); }
void init_DISTANCE_MAP()
{
int i, j;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
if (i == j)
{
DISTANCE_MAP[i][j] = 99999;
}
}
}
}
Point input_point(String prompt)
{
Point point;
do
{
} while (point > N - 1);
return point;
}
int main()
{
Route route;
init_DISTANCE_MAP();
route.start = input_point("出発地の地点番号を入力してください ==> ");
route.destination = input_point("目的地の地点番号を入力してください ==> ");
find_shortest(&route);
print_shortest(&route);
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRib29sLmg+CgojZGVmaW5lIE4gKDcpIC8qIOWcsOeCueOBruaVsCAqLwoKLyog5Zyw54K56ZaT6Led6ZuiICovCi8qIOKAuzEg5Zyw54K5YeOBqOWcsOeCuWLjgYzlkIzkuIDjga7lnLDngrnjga7loLTlkIjjga8w44GM5qC857SN44GV44KM44Gm44GE44KLICovCi8qIOKAuzIg5Zyw54K5YeOBqOWcsOeCuWLjgYzpmqPmjqXlnLDngrnjgafjgarjgYTloLTlkIjjga8tMeOBjOagvOe0jeOBleOCjOOBpuOBhOOCiyAqLwovKnN0YXRpYyovIGludCBESVNUQU5DRV9NQVBbTl1bTl0gPSB7CiAgICAvKmEgLT5iIDAgICAxICAgMiAgIDMgICA0ICAgNSAgIDYgKi8KICAgIC8qMCovIHsrMCwgKzIsICs4LCArNCwgLTEsIC0xLCAtMX0sCiAgICAvKjEqLyB7KzIsICswLCAtMSwgLTEsICszLCAtMSwgLTF9LAogICAgLyoyKi8geys4LCAtMSwgKzAsIC0xLCArMiwgKzMsIC0xfSwKICAgIC8qMyovIHsrNCwgLTEsIC0xLCArMCwgLTEsICs4LCAtMX0sCiAgICAvKjQqLyB7LTEsICszLCArMiwgLTEsICswLCAtMSwgKzl9LAogICAgLyo1Ki8gey0xLCAtMSwgKzMsICs4LCAtMSwgKzAsICszfSwKICAgIC8qNiovIHstMSwgLTEsIC0xLCAtMSwgKzksICszLCArMH0sCn07Cgp0eXBlZGVmIGNvbnN0IGNoYXIgKlN0cmluZzsKdHlwZWRlZiBpbnQgUG9pbnQ7CnR5cGVkZWYgaW50IERpc3RhbmNlOwojZGVmaW5lIERpc3RhbmNlX01BWCAoOTk5OTkpCgp0eXBlZGVmIHN0cnVjdCByb3V0ZQp7CiAgUG9pbnQgc3RhcnQsIGRlc3RpbmF0aW9uOwogIERpc3RhbmNlIGRpc3RhbmNlOwogIFBvaW50IHBvaW50W05dOwp9IFJvdXRlOwoKdm9pZCBmaW5kX3Nob3J0ZXN0KFJvdXRlICpyb3V0ZSkKewogIFBvaW50IHBvaW50OwogIERpc3RhbmNlIGRpc3RhbmNlLCBzaG9ydGVzdF9kaXN0YW5jZVtOXTsKICBib29sIGZpeGVkW05dOwoKICAvKiDliJ3mnJ/ljJYgKi8KICBmb3IgKHBvaW50ID0gMDsgcG9pbnQgPCBOOyBwb2ludCsrKQogIHsKICAgIHNob3J0ZXN0X2Rpc3RhbmNlW3BvaW50XSA9IERpc3RhbmNlX01BWDsKICAgIGZpeGVkW3BvaW50XSA9IGZhbHNlOwogIH0KICBzaG9ydGVzdF9kaXN0YW5jZVtyb3V0ZS0+c3RhcnRdID0gMDsKCiAgd2hpbGUgKHRydWUpCiAgewogICAgLyog5pyq56K65a6a5Zyw54K544KSMeOBpOaOouOBmSAqLwogICAgZm9yIChwb2ludCA9IDA7IHBvaW50IDwgTiAmJiBmaXhlZFtwb2ludF07IHBvaW50KyspCiAgICB7CiAgICB9CiAgICBpZiAocG9pbnQgPT0gTikKICAgICAgcmV0dXJuOwoKICAgIC8qIOacgOefrei3nembouOBjOOCiOOCiuefreOBhOWcsOeCueOCkuaOouOBmSAqLwogICAgZm9yIChpbnQgaSA9IHBvaW50ICsgMTsgaSA8IE47IGkrKykKICAgIHsKICAgICAgaWYgKCFmaXhlZFtpXSAmJiBzaG9ydGVzdF9kaXN0YW5jZVtpXSA8IHNob3J0ZXN0X2Rpc3RhbmNlW3BvaW50XSkKICAgICAgewogICAgICAgIHBvaW50ID0gaTsKICAgICAgfQogICAgfQogICAgZml4ZWRbcG9pbnRdID0gdHJ1ZTsKCiAgICAvKiDot53pm6Llho3oqIjnrpcgKi8KICAgIGZvciAoaW50IGkgPSAwOyBpIDwgTjsgaSsrKQogICAgewogICAgICBpZiAoZml4ZWRbaV0pCiAgICAgIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBkaXN0YW5jZSA9IERJU1RBTkNFX01BUFtwb2ludF1baV07CiAgICAgIGlmIChkaXN0YW5jZSA8PSAwKQogICAgICB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZGlzdGFuY2UgKz0gc2hvcnRlc3RfZGlzdGFuY2VbcG9pbnRdOwogICAgICBpZiAoZGlzdGFuY2UgPCBzaG9ydGVzdF9kaXN0YW5jZVtpXSkKICAgICAgewogICAgICAgIHNob3J0ZXN0X2Rpc3RhbmNlW2ldID0gZGlzdGFuY2U7CiAgICAgICAgcm91dGUtPnBvaW50W2ldID0gcG9pbnQ7CiAgICAgIH0KICAgIH0KICAgIHJvdXRlLT5kaXN0YW5jZSA9IHNob3J0ZXN0X2Rpc3RhbmNlW3JvdXRlLT5kZXN0aW5hdGlvbl07CiAgfQp9Cgp2b2lkIHByaW50X3JvdXRlKFJvdXRlICpyb3V0ZSwgUG9pbnQgZGVzdGluYXRpb24pCnsKICAvKiDnm67nmoTlnLDjgYvjgonlh7rnmbrlnLDjgb7jgafjga7ntYzot6/jgpLpgIbpoIbjgavjgZ/jganjgaPjgablh7rnmbrlnLDjgYvjgonooajnpLrjgZnjgosgKi8KICBpZiAocm91dGUtPnN0YXJ0ID09IGRlc3RpbmF0aW9uKQogIHsKICAgIHByaW50ZigiJWQiLCByb3V0ZS0+c3RhcnQpOwogIH0KICBlbHNlCiAgewogICAgcHJpbnRfcm91dGUocm91dGUsIHJvdXRlLT5wb2ludFtkZXN0aW5hdGlvbl0pOwogICAgcHJpbnRmKCIgLT4gJWQiLCBkZXN0aW5hdGlvbik7CiAgfQp9Cgp2b2lkIHByaW50X3Nob3J0ZXN0KFJvdXRlICpyb3V0ZSkKewogIHByaW50Zigi5Ye655m65Zyw44GL44KJ55uu55qE5Zyw44G+44Gn44Gu5pyA55+t57WM6LevXG4iKTsKICBwcmludF9yb3V0ZShyb3V0ZSwgcm91dGUtPmRlc3RpbmF0aW9uKTsKICBwcmludGYoIlxu5Ye655m65Zyw44GL44KJ55uu55qE5Zyw44G+44Gn44Gu5pyA55+t6Led6ZuiID0gJWRcbiIsIHJvdXRlLT5kaXN0YW5jZSk7Cn0KCnZvaWQgaW5pdF9ESVNUQU5DRV9NQVAoKQp7CiAgaW50IGksIGo7CiAgZm9yIChpID0gMDsgaSA8IE47IGkrKykKICB7CiAgICBmb3IgKGogPSAwOyBqIDwgTjsgaisrKQogICAgewogICAgICBpZiAoaSA9PSBqKQogICAgICB7CiAgICAgICAgRElTVEFOQ0VfTUFQW2ldW2pdID0gOTk5OTk7CiAgICAgIH0KICAgIH0KICB9Cn0KClBvaW50IGlucHV0X3BvaW50KFN0cmluZyBwcm9tcHQpCnsKICBQb2ludCBwb2ludDsKICBkbwogIHsKICAgIHByaW50ZigiJXMiLCBwcm9tcHQpOwogICAgc2NhbmYoIiVkIiwgJnBvaW50KTsKICB9IHdoaWxlIChwb2ludCA+IE4gLSAxKTsKICByZXR1cm4gcG9pbnQ7Cn0KCmludCBtYWluKCkKewogIFJvdXRlIHJvdXRlOwogIGluaXRfRElTVEFOQ0VfTUFQKCk7CgogIHJvdXRlLnN0YXJ0ID0gaW5wdXRfcG9pbnQoIuWHuueZuuWcsOOBruWcsOeCueeVquWPt+OCkuWFpeWKm+OBl+OBpuOBj+OBoOOBleOBhCA9PT4gIik7CiAgcm91dGUuZGVzdGluYXRpb24gPSBpbnB1dF9wb2ludCgi55uu55qE5Zyw44Gu5Zyw54K555Wq5Y+344KS5YWl5Yqb44GX44Gm44GP44Gg44GV44GEID09PiAiKTsKICBmaW5kX3Nob3J0ZXN0KCZyb3V0ZSk7CiAgcHJpbnRfc2hvcnRlc3QoJnJvdXRlKTsKCiAgcmV0dXJuIDA7Cn0=