#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_NUM 17
typedef struct Square_tag Square;
struct Square_tag {
char c;
int cost[MAX_NUM][MAX_NUM];
Square *ptr[MAX_NUM][MAX_NUM];
};
typedef struct {
Square *ary;
Square *start;
Square *goal;
int len_x;
int len_y;
} SquareInfo;
void get_pos(int len_x, int x, int y, int num, int *idx1, int *idx2) {
int x1, x2, y1, y2;
switch (num) {
case 0: x1 = -1; y1 = -1; x2 = 0; y2 = -1; break;
case 1: x1 = 1; y1 = 1; x2 = 0; y2 = 1; break;
case 2: x1 = 1; y1 = -1; x2 = 0; y2 = -1; break;
case 3: x1 = -1; y1 = 1; x2 = 0; y2 = 1; break;
case 4: x1 = -1; y1 = -1; x2 = -1; y2 = 0; break;
case 5: x1 = 1; y1 = 1; x2 = 1; y2 = 0; break;
case 6: x1 = -1; y1 = 1; x2 = -1; y2 = 0; break;
case 7: x1 = 1; y1 = -1; x2 = 1; y2 = 0; break;
case 8: x1 = 0; y1 = 0; x2 = 0; y2 = -1; break;
case 9: x1 = 0; y1 = 0; x2 = 0; y2 = 1; break;
case 10: x1 = 0; y1 = 0; x2 = -1; y2 = 0; break;
case 11: x1 = 0; y1 = 0; x2 = 1; y2 = 0; break;
case 12: x1 = 0; y1 = -1; x2 = 0; y2 = 0; break;
case 13: x1 = 0; y1 = 1; x2 = 0; y2 = 0; break;
case 14: x1 = -1; y1 = 0; x2 = 0; y2 = 0; break;
case 15: x1 = 1; y1 = 0; x2 = 0; y2 = 0; break;
default: x1 = 0; y1 = 0; x2 = 0; y2 = 0; break;
}
*idx1 = ((y + y1) * len_x) + (x + x1);
*idx2 = ((y + y2) * len_x) + (x + x2);
}
int get_direction(int num, int from) {
int direction;
switch (num) {
case 0: case 2: case 8: case 12: direction = (from) ? 0 : 1; break;
case 1: case 3: case 9: case 13: direction = (from) ? 1 : 0; break;
case 4: case 6: case 10: case 14: direction = (from) ? 2 : 3; break;
case 5: case 7: case 11: case 15: direction = (from) ? 3 : 2; break;
default: direction = -1;
}
return direction;
}
int get_cost(int num) {
int cost;
if (num < 12) {
cost = 2;
} else if (num < 16) {
cost = 1;
} else {
cost = 0;
}
return cost;
}
void print_square(SquareInfo *info) {
Square *ary;
int i_x, i_y, idx;
ary = info->ary;
for (i_y = 1; i_y < (info->len_y - 1); i_y++) {
for (i_x = 1; i_x < (info->len_x - 1); i_x++) {
idx = (i_y * info->len_x) + i_x;
}
}
}
int scan_square(SquareInfo *info, int *cost_p) {
Square *ary, *ptr, *goal;
int len_x, len_y, i_x, i_y, i_from, i_to, i_from_rev, i_to2, idx;
int min_cost, max_cost, change, cost, add_cost;
ary = info->ary;
goal = info->goal;
len_x = info->len_x;
len_y = info->len_y;
min_cost = 0x7FFFFFFF;
max_cost = -1;
change = 0;
for (i_y = 1; i_y < (len_y - 1); i_y++) {
for (i_x = 1; i_x < (len_x - 1); i_x++) {
idx = (i_y * len_x) + i_x;
for (i_from = 0; i_from < MAX_NUM; i_from++) {
for (i_to = 0; i_to < MAX_NUM; i_to++) {
cost = ary[idx].cost[i_from][i_to];
if (cost > 0) {
if ((&ary[idx] == goal) && (min_cost > cost)) min_cost = cost;
if ((&ary[idx] == goal) && (max_cost < cost)) max_cost = cost;
i_from_rev = ((i_from % 2) > 0) ? (i_from - 1) : (i_from + 1);
ptr = ary[idx].ptr[i_from][i_to];
for (i_to2 = 0; i_to2 < MAX_NUM; i_to2++) {
if (ptr && get_direction(i_from_rev, 1) != get_direction(i_to2, 2) && ptr->cost[i_from_rev][i_to2] == 0) {
add_cost = get_cost(i_to2);
ptr->cost[i_from_rev][i_to2] = cost + add_cost;
if ((ptr == goal) && (min_cost > (cost + add_cost))) min_cost = cost + add_cost;
if ((ptr == goal) && (max_cost < (cost + add_cost))) max_cost = cost + add_cost;
change++;
}
}
}
}
}
}
}
//printf("change=%d min_cost=%d max_cost=%d \n", change, min_cost, max_cost);
*cost_p = min_cost;
return change;
}
void create_square(int argc, char *argv[], SquareInfo *info) {
Square *ary;
int i, len, len_x, len_y, i_x, i_y, idx, sizeof_ary;
int i_from, i_to, idx1, idx2, idx3, idx4, cost;
char c;
len_x = 0;
for (i = 1; i < argc; i++) {
if (len_x < len) len_x = len;
}
len_x += 2;
len_y = (argc - 1) + 2;
sizeof_ary = len_y * len_x * sizeof(Square);
//printf("len_x=%d len_y=%d sizeof_ary=%d \n", len_x, len_y, sizeof_ary);
for (i_y = 0; i_y < len_y; i_y++) {
for (i_x = 0; i_x < len_x; i_x++) {
idx = (i_y * len_x) + i_x;
len
= (i_y
> 0 && i_y
< (len_y
- 1)) ? (strlen(argv
[i_y
]) + 1) : 0; c = (i_x > 0 && i_x < len) ? argv[i_y][i_x - 1] : '#';
ary[idx].c = c;
if (c == 'S') info->start = &ary[idx];
if (c == 'G') info->goal = &ary[idx];
}
}
for (i_y = 0; i_y < (len_y - 1); i_y++) {
for (i_x = 0; i_x < (len_x - 1); i_x++) {
idx = (i_y * len_x) + i_x;
for (i_from = 0; i_from < MAX_NUM; i_from++) {
get_pos(len_x, i_x, i_y, i_from, &idx1, &idx2);
for (i_to = 0; i_to < MAX_NUM; i_to++) {
if (get_direction(i_from, 1) == get_direction(i_to, 0) || ary[idx].c == '#') {
cost = -1;
} else {
get_pos(len_x, i_x, i_y, i_to, &idx3, &idx4);
if (ary[idx1].c != '#' && ary[idx2].c != '#' && ary[idx3].c != '#' && ary[idx4].c != '#') {
if (ary[idx1].c == 'S') {
cost = get_cost(i_from);
cost += get_cost(i_to);
} else {
cost = 0;
}
} else {
cost = -1;
}
}
ary[idx].cost[i_from][i_to] = cost;
if (cost >= 0) ary[idx].ptr[i_from][i_to] = &ary[idx3];
}
}
}
}
info->ary = ary;
info->len_x = len_x;
info->len_y = len_y;
}
int main_part11_270(int argc, char *argv[]) {
SquareInfo info;
int cost = -1;
create_square(argc, argv, &info);
print_square(&info);
while (scan_square(&info, &cost));
return 0;
}
int main(int argc, char *argv[]) {
char *argv1[] = {"", "S....", "#....", "..#..", "....G"};
char *argv2[] = {"", "S.....G", "......."};
if (argc <= 1) {
main_part11_270(sizeof(argv1) / sizeof(char*), argv1);
main_part11_270(sizeof(argv2) / sizeof(char*), argv2);
} else {
main_part11_270(argc, argv);
}
return 0;
}