UVA: 10010 - Where's Waldorf?
Background- We got to do 8-way searching in a grid here. Obviously 8-way recursion was choice here but I preferred hashing the grid first because judges inputs are doing multiple search on the same grid. Since there are n search on the same grid so it is better to hash all letters position in the grid O(n) operation which are starting positions for search. This has 0.012 sec of timing on UVA judges input. Certainly 8-way recursion will cost more.
C Implementation -
Background- We got to do 8-way searching in a grid here. Obviously 8-way recursion was choice here but I preferred hashing the grid first because judges inputs are doing multiple search on the same grid. Since there are n search on the same grid so it is better to hash all letters position in the grid O(n) operation which are starting positions for search. This has 0.012 sec of timing on UVA judges input. Certainly 8-way recursion will cost more.
C Implementation -
#include <iostream> #include <string> #include <cstring> #include <iterator> #include <vector> #include <map> #include <set> #include <algorithm> #include <cstdlib> #include <stdio.h> #include <string.h> using namespace std; #define _SKIP_LINE_ do{scanf("%*[^\n]"); getc(stdin);}while(0) const short size = 50; char GRID[size+1][size+2]; short M, N, W; vector<string> words; typedef pair<short, short> Pos; struct Compare { bool operator() (const Pos& lhs, const Pos& rhs) const { if(lhs.first == rhs.first) return lhs.second < rhs.second; else return lhs.first < rhs.first; } }; typedef set<Pos, Compare> Positions; map<char, Positions> Hash; void print() { for(short i = 1; i <= M; ++i) { for(short j = 1; j <= N; ++j) cout << GRID[i][j]; cout << endl; } copy(words.begin(), words.end(), ostream_iterator<string>(cout, "\n")); } void Search(const string& word) { Positions::const_iterator p = Hash[word[0]].begin(); Positions::const_iterator end = Hash[word[0]].end(); Positions::const_iterator prev = end; short n = word.size(); const char* w = word.c_str(); short x = 0; short r = 0; short c = 0; while(p != prev && p != end) { const short i = p->first; const short j = p->second; prev = p; switch(1) { // right case 1: if(j+n-1 <= N && strncmp(GRID[i]+j, w, n) == 0) break; // left case 2: if(j-n+1 >= 1) { for(c=j, x=0; c > 0 && x < n; --c,++x) if(GRID[i][c] != w[x]) break; if(x == n) break; } // down case 3: if(i+n-1 <= M) { for(r=i, x=0; r < i+n; ++r, ++x) if(GRID[r][j] != w[x]) break; if(x == n) break; } // up case 4: if(i-n+1 >= 1) { for(r=i, x=0; r > 0 && x < n; --r, ++x) if(GRID[r][j] != w[x]) break; if(x == n) break; } // up right digonal case 5: if(i-n+1 >= 1 && j+n-1 <= N) { for(r=i, c=j, x=0; r > 0 && c < j+n; --r, ++c, ++x) if(GRID[r][c] != w[x]) break; if(x == n) break; } // down right digonal case 6: if(i+n-1 <= M && j+n-1 <= N) { for(r=i, c=j, x=0; r < i+n && c < j+n; ++r, ++c, ++x) if(GRID[r][c] != w[c-j]) break; if(x == n) break; } // up left digonal case 7: if(i-n+1 >= 1 && j-n+1 >= 1) { for(r=i, c=j, x=0; r > 0 && c > 0 && x < n; --r, --c, ++x) if(GRID[r][c] != w[x]) break; if(x == n) break; } // down left digonal case 8: if(i+n-1 <= M && j-n+1 >= 1) { for(r=i, c=j, x=0; r < i+n && c > 0; ++r, --c, ++x) if(GRID[r][c] != w[r-i]) break; if(x == n) break; } default: ++p; } } if(p == end) cout << 0 << " " << 0 << endl; else cout << p->first << " " << p->second << endl; } /* main * * */ int main() { short test_cases = 0; cin >> test_cases; while(test_cases > 0 && cin.eof() != true) { cin >> M >> N; _SKIP_LINE_; Hash.clear(); // READ and Hash GRID for(short r=1; r <= M; ++r) { for(short c=1; c <= N; ++c) { cin >> GRID[r][c]; GRID[r][c] = ::tolower(GRID[r][c]); Hash[GRID[r][c]].insert(make_pair(r, c)); } GRID[r][N+1] = '\0'; _SKIP_LINE_; } // READ WORD cin >> W; _SKIP_LINE_; words.clear(); words.resize(W); for(short c=0; c < W; ++c) { getline(cin, words[c]); transform(words[c].begin(), words[c].end(), words[c].begin(), ::tolower); } for_each(words.begin(), words.end(), Search); if(--test_cases > 0) cout << endl; } return 0; }
No comments:
Post a Comment