5 changed files with 207 additions and 12 deletions
			
			
		@ -0,0 +1,161 @@ | 
				
			|||||
 | 
					#include <iostream> | 
				
			||||
 | 
					#include <vector> | 
				
			||||
 | 
					#include <complex> | 
				
			||||
 | 
					#include <deque> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					//#define ANIMATE
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					using namespace std; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					struct Input { | 
				
			||||
 | 
					    vector<vector<unsigned char>> map; | 
				
			||||
 | 
					    unsigned width; | 
				
			||||
 | 
					    unsigned height; | 
				
			||||
 | 
					    complex<int> start; | 
				
			||||
 | 
					    complex<int> end; | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					complex<int> dirs[] = { | 
				
			||||
 | 
					    complex<int>(1, 0), | 
				
			||||
 | 
					    complex<int>(0, 1), | 
				
			||||
 | 
					    complex<int>(-1, 0), | 
				
			||||
 | 
					    complex<int>(0, -1) | 
				
			||||
 | 
					}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Input parse() | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    Input data; | 
				
			||||
 | 
					    auto &map = data.map; | 
				
			||||
 | 
					    for (string line; getline(cin, line);) { | 
				
			||||
 | 
					        vector<unsigned char> row; | 
				
			||||
 | 
					        for (auto x : line) { | 
				
			||||
 | 
					            switch (x) { | 
				
			||||
 | 
					            case 'S': | 
				
			||||
 | 
					                data.start = complex<int>(row.size(), map.size()); | 
				
			||||
 | 
					                row.push_back('a' - 'a'); | 
				
			||||
 | 
					                break; | 
				
			||||
 | 
					            case 'E': | 
				
			||||
 | 
					                data.end = complex<int>(row.size(), map.size()); | 
				
			||||
 | 
					                row.push_back('z' - 'a'); | 
				
			||||
 | 
					                break; | 
				
			||||
 | 
					            default: row.push_back(x - 'a'); break; | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					        data.map.push_back(row); | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    data.width = map.front().size(); | 
				
			||||
 | 
					    data.height = map.size(); | 
				
			||||
 | 
					    return data; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#ifdef ANIMATE | 
				
			||||
 | 
					#include <fstream> | 
				
			||||
 | 
					unsigned render_frame = 0; | 
				
			||||
 | 
					void render(const Input &input, vector<vector<unsigned>> &dist, deque<complex<int>> &scan) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    auto scan_map = (bool (*)[input.width])new bool[input.width * input.height](); | 
				
			||||
 | 
					    for (auto &x : scan) { | 
				
			||||
 | 
					        scan_map[x.imag()][x.real()] = true; | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    char fname[] = "img/00000.pam"; | 
				
			||||
 | 
					    sprintf(fname, "img/%05u.pam", render_frame++); | 
				
			||||
 | 
					    auto file = ofstream(fname); | 
				
			||||
 | 
					    file << "P7\n"; | 
				
			||||
 | 
					    file << "WIDTH " << input.width << '\n'; | 
				
			||||
 | 
					    file << "HEIGHT " << input.height << '\n'; | 
				
			||||
 | 
					    file << "DEPTH 3\nMAXVAL 255\nTUPLTYPE RGB\nENDHDR\n"; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    unsigned maxdist = 0; | 
				
			||||
 | 
					    for (unsigned y = 0; y < input.height; y++) { | 
				
			||||
 | 
					        for (unsigned x = 0; x < input.width; x++) { | 
				
			||||
 | 
					            unsigned d = dist[y][x]; | 
				
			||||
 | 
					            if (d > maxdist) maxdist = d; | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    for (unsigned y = 0; y < input.height; y++) { | 
				
			||||
 | 
					        for (unsigned x = 0; x < input.width; x++) { | 
				
			||||
 | 
					            uint32_t color = 0; | 
				
			||||
 | 
					            color |= ((dist[y][x] * 0xFF / maxdist) & 0xFF) << 8; | 
				
			||||
 | 
					            color |= input.map[y][x] * 0xFF / 26; | 
				
			||||
 | 
					            if (scan_map[y][x]) color = 0xFF0000; | 
				
			||||
 | 
					            file.write((char *)&color, 3); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    file.close(); | 
				
			||||
 | 
					    delete scan_map; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					#endif | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					vector<vector<unsigned>> calc_dist(const Input &input) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    vector<vector<unsigned>> dist(input.height, vector<unsigned>(input.width)); | 
				
			||||
 | 
					    auto &map = input.map; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    deque<complex<int>> scan; | 
				
			||||
 | 
					    scan.push_back(input.end); | 
				
			||||
 | 
					    dist[input.end.imag()][input.end.real()] = 1; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    while (!scan.empty()) { | 
				
			||||
 | 
					        auto pos = scan.front(); | 
				
			||||
 | 
					        unsigned pos_d = dist[pos.imag()][pos.real()]; | 
				
			||||
 | 
					        unsigned pos_h = map[pos.imag()][pos.real()]; | 
				
			||||
 | 
					        scan.pop_front(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        for (auto dir : dirs) { | 
				
			||||
 | 
					            auto newpos = pos + dir; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            // Make sure the new position is in-bounds
 | 
				
			||||
 | 
					            if (newpos.imag() < 0 || newpos.imag() >= (int)input.height) continue; | 
				
			||||
 | 
					            if (newpos.real() < 0 || newpos.real() >= (int)input.width) continue; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            // If the distance for this position has already been calculated,
 | 
				
			||||
 | 
					            //  and is smaller than the current pos' distance, skip it.
 | 
				
			||||
 | 
					            unsigned &newpos_d = dist[newpos.imag()][newpos.real()]; | 
				
			||||
 | 
					            if (newpos_d && newpos_d <= pos_d + 1) continue; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            // Make sure the height difference isn't too big
 | 
				
			||||
 | 
					            unsigned newpos_h = map[newpos.imag()][newpos.real()]; | 
				
			||||
 | 
					            if ((int)pos_h - (int)newpos_h > 1) continue; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            // Otherwise, continue down this path
 | 
				
			||||
 | 
					            newpos_d = pos_d + 1; | 
				
			||||
 | 
					            scan.push_back(newpos); | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					#ifdef ANIMATE | 
				
			||||
 | 
					        render(input, dist, scan); | 
				
			||||
 | 
					#endif | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    return dist; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					unsigned p1(const Input &input, const vector<vector<unsigned>> &dist) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    unsigned end_dist = dist[input.start.imag()][input.start.real()]; | 
				
			||||
 | 
					    if (end_dist) end_dist--; | 
				
			||||
 | 
					    return end_dist; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					unsigned p2(const Input &input, const vector<vector<unsigned>> &dist) | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    unsigned smallest = dist[input.start.imag()][input.start.real()]; | 
				
			||||
 | 
					    for (unsigned y = 0; y < input.height; y++) { | 
				
			||||
 | 
					        for (unsigned x = 0; x < input.width; x++) { | 
				
			||||
 | 
					            if (input.map[y][x] == 0) { | 
				
			||||
 | 
					                unsigned d = dist[y][x]; | 
				
			||||
 | 
					                if (d && d < smallest) smallest = d; | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					    } | 
				
			||||
 | 
					    if (smallest) smallest--; | 
				
			||||
 | 
					    return smallest; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					int main() | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    auto input = parse(); | 
				
			||||
 | 
					    auto dist = calc_dist(input); | 
				
			||||
 | 
					    cout << p1(input, dist) << endl; | 
				
			||||
 | 
					    cout << p2(input, dist) << endl; | 
				
			||||
 | 
					} | 
				
			||||
								
									Binary file not shown.
								
							
						
					@ -0,0 +1,41 @@ | 
				
			|||||
 | 
					abcccccccccccccccccaaccccccccccccaaaaaaaacccccccccccaaaaaccccaaaaaaccaaaaaaaaaaaaaaaaaccccccccccccccccaaacccccaaaaaaaacccaaaccccccccccccccccccccccccccccccccccccccccccccccccccaaaaa | 
				
			||||
 | 
					abccccccccccccccccaaacaacccccccccccaaaacccccccccccccaaaaaacccaaaaaaccaaaaaaaaaaaaaaaaaaaacccccccccaaacaaacccccaaaaaaaaaccaaaaccccccccccccccccccccccccccccccccccccccccccccccccaaaaaa | 
				
			||||
 | 
					abcccccccccccccccccaaaaacccccccccccaaaaaccccccccccccaaaaaaccccaaaacccaaaacccaaaaaaaaaaaaacccccccccaaaaaaaaaacccaaaaaaaaccaaaaccccccccccccccccccccccccccccccccccaaacccccccccccaaaaaa | 
				
			||||
 | 
					abcccccccccccccccaaaaaacccccccccccaaacaaccaaccccccccaaaaaaccccaaaacccaaaccccaaaaaaaaaaaaaccccccccccaaaaaaaaaccaaaaaacccccaaacccccccccccccccccccccccccccccccccccaaaccccccccccccccaaa | 
				
			||||
 | 
					abcccccccccccccccaaaaaaaacccccccccaacccacaaacaacccccccaaccccccaccaccccccccaaaaaaaaaaaaccccccccccccccaaaaaaacccaaaaaaacccccccccccccaacccccccccccccccccccccccccccaaaccccccccccccccaaa | 
				
			||||
 | 
					abcccccccccccccccaacaaaaacccccccccccccccccaaaaacccccccccccccccccccccccccccaaaaaaaaaaaaccccccccccccccaaaaaaccccaaccaaacccccccccccaaaaaaccccccccccccccccccccccccccdccccccccccccccccaa | 
				
			||||
 | 
					abccaacccccccaaacccaaacaccccccccccaaacccaaaaaaccccccccccccccccccccccccccccaaacccaaaaaacaaaaccccccccaaaaaaaccccccccaaacccccccccccaaaaaacccccccccccccccccllllllcccdddddcccccccccccccc | 
				
			||||
 | 
					abaaaacccacccaaccccaacccccccccccccaaacccaaaaaaaacccccccccccccccccaaccccccccacccaaaaccccaaaaccccccccaaacaaaccccccccccccccccccccccaaaaaaccccccccccccccccllllllllldddddddddddccaaccccc | 
				
			||||
 | 
					abaaaaccaaaaaaaacccccccccccccccaaaaaaaacaacaaaaacccccccccccccccccaaacccccccaaacaaccccccaaaacccccccccccccaaccccccccccccccccccccccaaaaaccccccccccccccccclllllllllldddddddddeeaaaccccc | 
				
			||||
 | 
					abaaaccccaaaaaaaaccccccccaaacccaaaaaaaacccaaacccccccccccccccccaaaaaaaaccccccaaaaacccccccaacccccccccccccccccccccccccccccccccccccccaaaaccccaaaccccccccckllppppplllmmmmmmmdeeeeaaccccc | 
				
			||||
 | 
					abaaaacccaaaaaaaaacccccaaaaaaccccaaaaaccccaaccccccccccccccccccaaaaaaaaccccccaaaaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccaaaacccccccckklpppppppplmmmmmmmmmeeeeaccccc | 
				
			||||
 | 
					abaaaacccaaaaaaaaacccccaaaaaacccaaaaaaccccccccaacccccccccccccccaaaaaaccccccaaaaaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccaaaacccccccckkkppppppppqmmmmmmmmmmeeeaacccc | 
				
			||||
 | 
					abaaaaaccaaaaaaaaccccccaaaaaacccaaaaaaccccccacaaaacccccccccccccaaaaaaccccccaaaaaaaaccccccccaaaaccccccccaaacccccccccccccccccccccccccccccccaaacccccccckkkpppuuuppqqqqqqqqmmmeeeeacccc | 
				
			||||
 | 
					abacccccaaaaaaaccccccccaaaaaccccaccaaaccccccaaaaaacccccacccccccaaaaaaccccccaaaaaacaaaccccccaaaaccccccccaaaacccccccccccccccccccccccccccccccccccccccckkkpppuuuuuuqqqqqqqqqnnneeeccccc | 
				
			||||
 | 
					abcccccccaccaaaccccccccaaaaacccccccccccccccccaaaacccaaaacccccccaacaaacccccccccaaacaaaaaccccaaaaccccccccaaaaccccccccccccccccccccccccccccccccccccccckkkkpppuuuuuuuqvvvvqqqnnneeeccccc | 
				
			||||
 | 
					abcccccccccccaaacaaccccccccccccccccccccccccccaaaacccaaaaaacccccccccccccccccccccccaaaaaaccccaaacccccccccaaaccccccccccccccccccccccccccccccccccccccckkkkrrpuuuxxxuvvvvvvvqqnnneeeccccc | 
				
			||||
 | 
					abcccccccccccccccaacaaaccccccccccccccccccccccaacaacccaaaaacccccccccccccccccccccccaaaaaaccccccccccccccccccccccccccccccccccccccccccccccccccccccccckkkkrrrruuxxxxuvvvvvvvqqnnneeeccccc | 
				
			||||
 | 
					abcccccccccccccccaaaaacccccccccccccccccccccccccccaccaaaaacccccaaccccccccccccccccccaaaaaccccccccccccccccaaaccccccccccccccaaacccccccccccccccccccckkkkrrrruuuxxxxyyyyyvvvqqnnneecccccc | 
				
			||||
 | 
					abcccccccccccccaaaaaacccccccccccaacaacccccccccccaaaaaaaaacccacaaaacaaccaaccccccccaaacaaccccccccccaaccccaaaaaacccaacaacccaaacacccccccccccccccccjjkkrrrruuuuuxxxyyyyyvvqrqnneffcccccc | 
				
			||||
 | 
					abcccccccccccccaaaaaaaacccaaacccaaaaaccccccaacccaaaaaaaaacccaaaaaacaaaaaaccccccccaaacaaacccccccaaaaaacaaaaaaacccaaaaacaaaaaaaaccccccccccccccccjjjrrrtttuuxxxxxyyyyyvvrrnnnfffcccccc | 
				
			||||
 | 
					SbccccccccccccccccaaaaacccaaaaccaaaaaaccccaaaaaacaaaaaaaaacccaaaacccaaaaaccccccccaaaaaaacccccccaaaaaaaaaaaaaaccaaaaaccaaaaaaaaccccccccccccccccjjjrrrtttxxxEzzzzyyyvvrrrnnnfffcccccc | 
				
			||||
 | 
					abccccccccccaaaccaaccaacccaaaaccaaaaaacccccaaaaacaaaaaaaaacccaaaaccaaaaaacccccccccaaaaaaccccccccaaaacaaaaaaacccaaaaaaccaaaaaacccccccccccccccccjjjrrrtttxxxxxyyyyyyvvrrrnnnfffcccccc | 
				
			||||
 | 
					abcccccccccaaaaccaacccccccaaacccaaaaaacccaaaaaaaaaaaaaaaaacccaacacaaaaaaaacccccaaaaaaaacccccccccaaaacccaaaaaaccccaaaacccaaaaacccccccccccccccccjjjrrrtttxxxxxyyyyyyywvrrnnnfffcccccc | 
				
			||||
 | 
					abcccccccccaaaacccccccccccccccccccaaaccccaaaaaaaaaaaaaaaaaacccccccaaaaaaaacccccaaaaaaaaaccccccccaccacccaaaaaaccccacccccaaaaaacccccccccccccccccjjjrrrrttttxxxyyyyyyywwrrroooffcccccc | 
				
			||||
 | 
					abccccccccccaaaccccccccccccccccccccccccccaaaaaaaaaccaaaaaaaccccccccccaaccccccccaaaaaaaaaaccccccccccccccaacccccccccccccccaaccccccccccccccccccccjjjjqqqqttttxxyywwwwwwwwrrooofffccccc | 
				
			||||
 | 
					abcccccccccccccccccccccccccccccccccccccccccaaacacccccaaaaccccccccccccaacccccccccccaaacaaacccccccccccccccccccccccccccccaaacccccccccccccccccccaacjjjjqqqqqttwwwwwwwwwwwrrrooofffccccc | 
				
			||||
 | 
					abcccccccccccccccccccccccccccccccccccccccccaaccccccccccaacccccccccccccccccccccccccaaacccccccccccccccccccccccccccccccccaaacccccccccccccccccaaaaaajjjjqqqqttwwwwwwsswwrrrrooofffccccc | 
				
			||||
 | 
					abcccccaaaaccccccccccccccaacaaccccccccccccccccccccccccccccccccccccccccccccccccccccaacccccccccccccccccccccccccccccccaaaaaaaaccaaaacccccccccaaaaaacjjjiqqqtttwwwwsssssrrrrooofffccccc | 
				
			||||
 | 
					abccccaaaaaccccccccccccccaaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaaaaccaaaaacccccccccaaaaacciiiiqqttswwwssssssrrroooogffccccc | 
				
			||||
 | 
					abccccaaaaaacccccccccccccaaaaaacccaaaccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaccaaaaaaccccccccaaaaacccciiiqqqssssssspppooooooogggaccccc | 
				
			||||
 | 
					abccccaaaaaaccccccccaacccaaaaaaccccaacccccccccccccccccccccccccccccccccaaaaccccccccccccccccccccccccccccccccccccccccccaaaaaaccaaaaaaccccccccaaaaaccccciiiqqsssssspppppoooooggggaacccc | 
				
			||||
 | 
					abccccaaaaaccccccaaaaacccaaaaaacaacaaaaaccccccccccccccccccccaacccccccaaaaacccccccccccaaaccccccccccccccccccccccccccccaaaaaacccaaaaacccccccccacccccccciiiqqqpssspppppgggggggggaaacccc | 
				
			||||
 | 
					abccccccaaacccccccaaaaaccccaaaccaaaaaaaacccccccaacccccccaaccaacccccccaaaaaacccccccccaaaacccccccccccaaaaccccccccccccaaccaaacccaaacccccaaacaaaccccccccciiqqppppppphhhggggggggaaaacccc | 
				
			||||
 | 
					abccccccccccccccccaaaaaccccccccccaaaaaccccccccaaacaaccccaaaaaacccccccaaaaaaaccccccccaaaacccccccccccaaaacccccccccaaaaaacccccccccccccccaaaaaaaccccccccciiippppppphhhhggggggcaaacccccc | 
				
			||||
 | 
					abaacccccccccccccaaaaaccccccccccccaaaaaccccccccaaaaacccccaaaaaaacccccaaaaacaaacccccccaaacccccccccccaaaacccccccccaaaaacccccccccccccccccaaaaaacccccccccciiiippphhhhhhcccccccaaacccccc | 
				
			||||
 | 
					abaacccccccccccccccaaacccccccccccaaacaaccccccaaaaaaccccccaaaaaaacccaaccaaacaaaaccaaaccccccccccccccccaaacccccccccaaaaaaacccccccccccccccaaaaaaaacccccccciiihhhhhhhhaaaccccccccccccccc | 
				
			||||
 | 
					abaaccccccccccccccccccccccccccccccaacccccccccaaaaaaaacccaaaaaaccaaaaaacccccaaaacaaaaaccccccccccccccccccccccccccaaaaaaaaccccccccccccccaaaaaaaaaccccccccciihhhhhhcaaaacccccccccccccca | 
				
			||||
 | 
					abaaccccccccccccccccccccccccccccccccaacccccccaacaaaaacccaaaaaaccaaaaacccccccaaaaaaaacccccccccccccccccccccccccccaaaaaaaacccccccccaaacaaaaaaaaaacccccccccccchhhaccccaacccccccccccccca | 
				
			||||
 | 
					abaaccccccccccccccccccccccccccccccccaaaaaaccccccaaccccccccccaaccaaaaaaacccccaaaaaaaccccccccccccccccccccccccaaaccacaaacccccccccccaaaaaaacaaacaaaaaacccccccccaaacccccccccccccccaaaaaa | 
				
			||||
 | 
					abccccccccccccccccccccccccccccccccccaaaaaccccccaaccccccccccccccaaaaaaaacaaaaaaaaaaccccccccccccccccccccccccaaaaaaccaaaccccccccccccaaaaaacaaacaaaaaacccccccccaaaccccccccccccccccaaaaa | 
				
			||||
 | 
					abccccccccccccccccccccccccccccccccaaaaaaaacccccccccccccccccccccaaaaaaaacaaaaaaaaaaaaacccccccccccccccccccccaaaaaacccccccccccccccaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccaaaaa | 
				
			||||
@ -0,0 +1,2 @@ | 
				
			|||||
 | 
					484 | 
				
			||||
 | 
					478 | 
				
			||||
@ -1,13 +1,4 @@ | 
				
			|||||
#!/bin/sh | 
					#!/bin/sh | 
				
			||||
rm img/*.gif | 
					ffmpeg -threads 0 -pattern_type glob -i "img/*.pam" -r 60 \ | 
				
			||||
waitjobs() { | 
					    -filter:v "setpts=0.05*PTS,scale=iw*4:ih*4:flags=neighbor" \ | 
				
			||||
    while [ "$(jobs -p | wc -l)" -ge "$1" ]; do wait; done | 
					    anim.webm | 
				
			||||
} | 
					 | 
				
			||||
for x in img/*.pam; do | 
					 | 
				
			||||
    echo "$x" | 
					 | 
				
			||||
    pamtogif -quiet "$x" > "$x.gif" & | 
					 | 
				
			||||
    waitjobs "$(nproc)" | 
					 | 
				
			||||
done | 
					 | 
				
			||||
wait | 
					 | 
				
			||||
gifsicle -d1 --verbose img/*.gif > anim.gif | 
					 | 
				
			||||
ffmpeg -i anim.gif -filter:v "setpts=0.1*PTS,scale=iw*4:ih*4:flags=neighbor" -r 100 anim.webm | 
					 | 
				
			||||
 | 
				
			|||||
					Loading…
					
					
				
		Reference in new issue