This is actually more difficult than Problem 2, which I completed first.
mirror.cpp
#include <iostream>
#include <fstream>
#define loopi(x) loop_start(i,x,0)
#define loopj(x) loop_start(j,x,0)
#define loop_start(i,x,s) for(int i = (s); i < (x); ++i)
#define loop_rev(a,x,stop) for(int a = (x); a >= (stop); --a)
using namespace std;
int N, M; // [1, 1000]
int num_mirrors, max_depth;
char *grid;
// + = right and down
int length(int x, int y, char dx, char dy)
{
int pos = x + y * M;
int depth = 1;
for(;;)
{
// Loop limit
if(depth > max_depth) return -1;
// Bounce
if(grid[pos] == '/')
{
if(dy) { dx = -dy; dy = 0; }
else { dy = -dx; dx = 0; }
}
else // '\'
{
if(dy) { dx = +dy; dy = 0; }
else { dy = +dx; dx = 0; }
}
// Check if it leaves the board
if(dy)
{
if(dy > 0) // down
{
++y;
if(y >= N)
return depth;
pos += M;
}
else // up
{
//if(y - 1 < 0) -> (y < 1) -> y <= 0
if(!y)
return depth;
--y;
pos -= M;
}
}
else
{
if(dx > 0) // right
{
++x;
if(x >= M)
return depth;
++pos;
}
else // left
{
//if(x - 1 < 0) -> (x < 1) -> (x <= 0)
if(!x)
return depth;
--x;
--pos;
}
}
// Continue the loop
++depth;
}
return depth;
}
int best_path(){
int longest = 0;
#define test(a, b, c, d) { \
int result = length(a, b, c, d); \
if(result == -1) return -1; \
else if(result > longest) \
longest = result; \
}
// Top
loopi(M) test(i, 0, 0, +1)
// Bottom
loopi(M) test(i, N - 1, 0, -1)
// Left
loopi(N) test(0, i, +1, 0)
// Right
loopi(N) test(N - 1, i, -1, 0)
return longest;
}
int main() {
ofstream fout ("mirror.out");
ifstream fin ("mirror.in");
// Read input
fin >> N >> M;
num_mirrors = N * M;
max_depth = num_mirrors << 1; // some mirrors can be reflected on their back side
grid = new char[num_mirrors];
loopi(num_mirrors)
fin >> grid[i];
// Calculate output
fout << best_path() << endl;
return 0;
}
No comments:
Post a Comment