Az alábbi letöltési lehetőségek közül választhatsz: (
segítség)
Típus: text/plain
Tartalmaz szöveget
Karakterkódolás: us-ascii
Méret: 9 KB
#include <stdio.h>
#define MaxSize 257
#define MaxLen 65025
typedef unsigned char byte;
class cRoute;
class cLab;
class cRoute {
private:
int Len;
enum eStep {
S_Forward,
S_Left,
S_Right
} Step[MaxLen];
public:
void Init (void);
int GetLen (void) {return Len;}
void Push (eStep);
void PushForward (void) {Push(S_Forward);}
void PushLeft (void) {Push(S_Left);}
void PushRight (void) {Push(S_Right);}
eStep ChangeDirection (eStep);
void Simplify (void);
void MarkInLab (cLab &);
void PrintToFile (FILE *);
};
class cLab {
private:
int Size;
enum eField {
F_Space,
F_Wall,
F_Footprint,
} Field[MaxSize][MaxSize];
cRoute Route;
public:
enum eDir {
D_Right,
D_Up,
D_Left,
D_Down
};
void Run (const char *, const char *, const char *);
bool Read (const char *);
bool Write (const char *);
static eDir DirTurnLeft (eDir);
static eDir DirTurnRight (eDir);
static eDir DirTurnBack (eDir);
static void MoveDir (int &, int &, eDir);
void SetField (int, int, eField);
void SetFieldSpace (int X, int Y) {SetField(X, Y, F_Space);}
void SetFieldWall (int X, int Y) {SetField(X, Y, F_Wall);}
void SetFieldFootprint (int X, int Y) {SetField(X, Y, F_Footprint);}
eField GetField (int, int);
eField GetFieldDir (int, int, eDir);
void Start (int &, int &, eDir &);
bool Exit (int, int);
void DeleteFootprints (void);
void BuildLeftHandRoute (void);
void BuildShortestRoute (void);
};
int main (int AN, char * Args []) {
cLab Lab;
if (AN < 4)
return 1;
Lab.Run(Args[1], Args[2], Args[3]);
return 0;
}
void cRoute::Init (void) {
Len = 0;
}
void cRoute::Push (eStep S) {
if (Len >= MaxLen)
return;
Step[Len++] = S;
}
cRoute::eStep cRoute::ChangeDirection (cRoute::eStep Step) {
if (Step == S_Right)
return S_Left;
else if (Step == S_Left)
return S_Right;
else
return Step;
}
void cRoute::Simplify (void) {
int I, J = 0, K, Right = 0;
bool bChange;
for (I = 0; I < Len; I++) {
if (Step[I] == S_Right)
Right++;
else
Right = 0;
if (Right == 2) {
bChange = true;
for (K = 1; true; K++) {
if (Step[I + K] == S_Forward) {
if (Step[J - K - 1] != S_Forward)
break;
} else {
if (Step[J - K - 1] == S_Forward)
break;
else if (Step[J - K - 1] == Step[I + K]) {
bChange = false;
K++;
break;
}
}
}
if (bChange) {
Step[I + K] = ChangeDirection(Step[I + K]);
Step[J - K - 1] = ChangeDirection(Step[J - K - 1]);
}
I += K;
J -= K;
}
Step[J++] = Step[I];
}
Len -= I - J;
}
void cRoute::MarkInLab (cLab & Lab) {
int I, X, Y;
cLab::eDir Dir;
Lab.Start(X, Y, Dir);
Lab.SetFieldFootprint(X, Y);
for (I = 0; I < Len; I++)
switch (Step[I]) {
case S_Forward:
Lab.MoveDir(X, Y, Dir);
Lab.SetFieldFootprint(X, Y);
break;
case S_Left:
Dir = Lab.DirTurnLeft(Dir);
break;
case S_Right:
Dir = Lab.DirTurnRight(Dir);
break;
}
}
void cRoute::PrintToFile (FILE * F) {
int I, J;
for (I = 0; I < Len; I++)
switch (Step[I]) {
case S_Forward: fprintf(F, "E"); break;
case S_Left: fprintf(F, "B"); break;
case S_Right: fprintf(F, "J"); break;
}
fprintf(F, "\n");
}
void cLab::Run (const char * In, const char * OutA, const char * OutB) {
Read(In);
BuildLeftHandRoute();
Route.MarkInLab(*this);
Write(OutB);
DeleteFootprints();
BuildShortestRoute();
Route.MarkInLab(*this);
Write(OutA);
}
bool cLab::Read (const char * FN) {
FILE * F = fopen(FN, "r");
if (F == NULL)
return false;
int I, J;
char Str[MaxSize + 1];
fscanf(F, "%d\n", &Size);
if (Size > MaxSize) {
fclose(F);
return false;
}
Size += 2;
for (I = 0; I < Size; I++) {
fgets(Str, MaxSize + 1, F);
for (J = 0; J < Size; J++) {
switch (Str[J]) {
case ' ':
SetFieldSpace(J, I);
break;
case '#':
SetFieldWall(J, I);
break;
}
}
}
fclose(F);
return true;
}
bool cLab::Write (const char * FN) {
FILE * F = fopen(FN, "w");
if (F == NULL)
return false;
int I, J;
fprintf(F, "%d\n", Route.GetLen());
Route.PrintToFile(F);
for (I = 0; I < Size; I++) {
for (J = 0; J < Size; J++)
switch (GetField(J, I)) {
case F_Space: fputc(' ', F); break;
case F_Wall: fputc('#', F); break;
case F_Footprint: fputc('.', F); break;
}
fprintf(F, "\n");
}
fclose(F);
return true;
}
cLab::eDir cLab::DirTurnLeft (cLab::eDir Dir) {
switch (Dir) {
case D_Right: return D_Up;
case D_Up: return D_Left;
case D_Left: return D_Down;
case D_Down: return D_Right;
}
}
cLab::eDir cLab::DirTurnRight (cLab::eDir Dir) {
switch (Dir) {
case D_Right: return D_Down;
case D_Up: return D_Right;
case D_Left: return D_Up;
case D_Down: return D_Left;
}
}
cLab::eDir cLab::DirTurnBack (cLab::eDir Dir) {
switch (Dir) {
case D_Right: return D_Left;
case D_Up: return D_Down;
case D_Left: return D_Right;
case D_Down: return D_Up;
}
}
void cLab::MoveDir (int & X, int & Y, eDir Dir) {
switch (Dir) {
case D_Right: X++; return;
case D_Up: Y--; return;
case D_Left: X--; return;
case D_Down: Y++; return;
}
}
inline void cLab::SetField (int X, int Y, cLab::eField F) {
if (X >= 0 && X < Size && Y >= 0 && Y < Size)
Field[Y][X] = F;
}
inline cLab::eField cLab::GetField (int X, int Y) {
return X >= 0 && X < Size && Y >= 0 && Y < Size ? Field[Y][X] : F_Wall;
}
cLab::eField cLab::GetFieldDir (int X, int Y, eDir Dir) {
MoveDir(X, Y, Dir);
return GetField(X, Y);
}
inline void cLab::Start (int & X, int & Y, eDir & Dir) {
X = 0;
Y = 1;
Dir = D_Right;
}
inline bool cLab::Exit (int X, int Y) {
return X == Size - 1 && Y == Size - 2;
}
void cLab::DeleteFootprints (void) {
int I, J;
for (I = 0; I < Size; I++)
for (J = 0; J < Size; J++)
if (Field[I][J] == F_Footprint)
Field[I][J] = F_Space;
}
void cLab::BuildLeftHandRoute (void) {
int X, Y;
eDir Dir;
Start(X, Y, Dir);
Route.Init();
while (!Exit(X, Y)) {
if (GetFieldDir(X, Y, DirTurnLeft(Dir)) != F_Wall) {
Dir = DirTurnLeft(Dir);
Route.PushLeft();
} else if (GetFieldDir(X, Y, Dir) != F_Wall) {
} else if (GetFieldDir(X, Y, DirTurnRight(Dir)) != F_Wall) {
Dir = DirTurnRight(Dir);
Route.PushRight();
} else {
Dir = DirTurnBack(Dir);
Route.PushRight();
Route.PushRight();
}
MoveDir(X, Y, Dir);
Route.PushForward();
}
}
void cLab::BuildShortestRoute (void) {
Route.Simplify();
}