hihoCoder#1120 小Hi小Ho的惊天大作战:扫雷・三 - 李舜阳 - 博客园


hihoCoder#1120 小Hi小Ho的惊天大作战:扫雷・三 - 李舜阳 - 博客园
http://hihocoder.com/problemset/problem/1120

输入

每个测试点(输入文件)存在多组测试数据。
每个测试点的第一行为一个整数Task,表示测试数据的组数。
在一组测试数据中:
第1行为2个整数N,M,表示迷宫的大小。
接下来的N行,每行M个整数,为一个矩阵A,用以描述整个迷宫,其中对于每一个格子A[i][j],若A[i][j]=-1,则表示该格子没有被探明,若0<=a[i][j]<=8,则表示该格子已经被探明了,且数值代表该格子附近8个格子中的地雷数。<>
对于100%的数据,满足:5<=N、M<=10, -1<=a[i][j]<=8。<>
对于100%的数据,满足:符合数据描述的迷宫一定存在。
对于100%的数据,满足:迷宫中没有探明的格子的数量K<=10。<>

输出

对于每组测试数据,输出2个整数,分别为一定为地雷的未探明格子数和一定不为地雷的未探明格子数。


样例输入
2
10 10
  0  0  1  2 -1  1  0  0  1 -1
  1  1  1 -1  2  1  0  0  1  1
 -1  1  1  1  1  0  0  0  0  0
  1  1  0  0  0  1  1  1  0  0
  0  0  0  0  0  1 -1  1  0  0
  0  0  0  0  0  2  2  2  0  0
  0  0  0  0  0  1 -1  1  0 -1
  0  0  0  0  0  1  1  1  0  0
  0  0  0  0  1  1  1  0  0  0
 -1  0  0 -1  1 -1  1  0  0  0
9 10
  0  0  0  0  0 -1  0  0 -1  0
  0  0 -1  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  1  1  1
  0  0  0  0  0  1  2  3 -1  1
  0  0  0  0 -1  1 -1 -1  3  1
  1  1  0  0  0  1  3 -1  2  0
 -1  1  0  0  0  0  1  1 -1  0
  1  1  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0
样例输出
7 3
5 5
看上去非常复杂, 实际上是这一系列最简单的一步,本质上是个搜索过程,相比于前一道题,可以不用策略三,而且题目的数据规模超级小,所以暴力搜索就能过。
把尚未确定的点放在一个unsettled列表里,然后依次枚举每个点的情况:是地雷or不是地雷
优化方案一即:每次枚举后,使用规则一、规则二对列表里剩下的点进行判断,如果能直接判断出是不是地雷的就立即设置了,这样剩下的枚举位就少了。当然回溯的时候记得把这些拓展出来的也要一并回溯。
优化方案二即:周围已知地雷数少的点优先枚举。(这个优化没做)

于是问题来了:给出一张N*M(在经过三条规则的反复洗礼之后,N和M都并不会很大)的地图,其中的某些格子已经被探明,探明的格子中都标有一个数字,表明与它相邻的8个格子里的地雷数量,而没有探明的格子里可能会有一些地雷。
而现在小Ho需要做的便是:判断出这张地图中的哪些格子里一定是地雷,哪些格子里一定不是地雷。(在多解情况下,一定是地雷以及一定不是地雷的定义指的是在每一种可行解中都是地雷或者都不是地雷
 
 8 struct point {
  9   int r;
 10   int c;
 11   int v;
 12   point(int _r, int _c) : r(_r), c(_c) {};
 13   point(int _r, int _c, int _v) : r(_r), c(_c), v(_v) {};
 14   bool operator==(const point &o) {return o.r == r && o.c == c;}
 15   bool operator!=(const point &o) {return o.r != r || o.c != c;}
 16 };
 17 
 18 #define SIZE 40
 19 
 20 int N, M;
 21 int field[SIZE][SIZE];
 22 int ans[SIZE][SIZE];
 23 int unset[SIZE][SIZE];
 24 vector<point> unsettled;
 25 
 26 bool valid(point &p) {
 27   return p.r >= 0 && p.r < N && p.c >= 0 && p.c < M;
 28 }
 29 
 30 vector<point> neighbors(point p) {
 31   vector<point> res;
 32 
 33   for (int i = -1; i < 2; i++) {
 34     for (int j = -1; j < 2; j++) {
 35       point q(i + p.r, j + p.c);
 36       if (valid(q) && q != p)
 37         res.push_back(q);
 38     }
 39   }
 40 
 41   return res;
 42 }
 43 
 44 void merge(point p) {
 45   if (ans[p.r][p.c] == -1 || ans[p.r][p.c] == p.v)
 46     ans[p.r][p.c] = p.v;
 47   else
 48     ans[p.r][p.c] = -2;
 49 }
 50 
 51 int around(point p, int s) {
 52   vector<point> nbs = neighbors(p);
 53   int res = 0;
 54 
 55   for (auto q : nbs) {
 56     if (field[q.r][q.c] >= 0 && s == 0) {
 57       res++;
 58       continue;
 59     }
 60     else
 61       res += unset[q.r][q.c] == s ? 1 : 0;
 62   }
 63 
 64   return res;
 65 }
 66 
 67 bool check(point p) {
 68   vector<point> nbs = neighbors(p);
 69   int mine = around(p, 1);
 70   int not_mine = around(p, 0);
 71   return (mine <= field[p.r][p.c] && field[p.r][p.c] + not_mine <= nbs.size());
 72 }
 73 
 74 bool check() {
 75   bool is_ok = true;
 76 
 77   for (auto p : unsettled) {
 78     if (!is_ok)
 79       break;
 80     vector<point> nbs = neighbors(p);
 81     for (auto q : nbs) {
 82       if (field[q.r][q.c] >= 0 && !check(q)) {
 83         is_ok = false;
 84         break;
 85       }
 86     }
 87   }
 88 
 89   return is_ok;
 90 }
 91 
 92 void extend() {
 93   bool over = false;
 94 
 95   while (!over) {
 96     over = true;
 97     for (auto p : unsettled) {
 98       vector<point> nbs = neighbors(p);
 99       for (auto q : nbs) {
100         if (field[q.r][q.c] < 0)
101           continue;
102 
103         vector<point> os = neighbors(q);
104         int mine = around(p, 1);
105         int not_mine = around(q, 1);
106 
107         if (field[q.r][q.c] + not_mine == os.size()) {
108           for (auto o : os) {
109             if (o.v == -1) {
110               over = false;
111               o.v = 1;
112               unset[o.r][o.c] = 1;
113             }
114           }
115         }
116         if (mine == field[q.r][q.c]) {
117           for (auto o : os) {
118             if (o.v == -1) {
119               over = false;
120               o.v = 0;
121               unset[o.r][o.c] = 0;
122             }
123           }
124         }
125       }
126     }
127   }
128 }
129 
130 void solve(int pos) {
131   if (pos >= unsettled.size()) {
132     for (auto p : unsettled) {
133       merge(p);
134     }
135     return;
136   }
137 
138   if (unsettled[pos].v != -1) {
139     solve(pos + 1);
140     unsettled[pos].v = -1;
141     unset[unsettled[pos].r][unsettled[pos].c] = -1;
142     return;
143   }
144 
145   for (int i = 0; i < 2; i++) {
146     unsettled[pos].v = i;
147     unset[unsettled[pos].r][unsettled[pos].c] = i;
148     if (!check())
149       continue;
150     extend();
151     solve(pos + 1);
152   }
153   unsettled[pos].v = -1;
154   unset[unsettled[pos].r][unsettled[pos].c] = -1;
155 }
156 
157 int main() {
158   int n;
159 
160   cin >> n;
161   while (n--) {
162     cin >> N >> M;
163     memset(ans, -1, SIZE * SIZE * sizeof(int));
164     memset(unset, -1, SIZE * SIZE * sizeof(int));
165     unsettled.clear();
166     for (int i = 0; i < N; i++) {
167       for (int j = 0; j < M; j++) {
168         cin >> field[i][j];
169         if (field[i][j] < 0)
170           unsettled.push_back(point(i, j, -1));
171       }
172     }
173 
174     solve(0);
175 
176     int mine = 0;
177     int not_mine = 0;
178 
179     for (auto p : unsettled) {
180       mine += (ans[p.r][p.c] == 1 ? 1 : 0);
181       not_mine += (ans[p.r][p.c] == 0 ? 1 : 0);
182     }
183 
184     cout << mine << " " << not_mine << endl;
185 
186   }
187 
188   return 0;
189 }
Read full article from hihoCoder#1120 小Hi小Ho的惊天大作战:扫雷・三 - 李舜阳 - 博客园

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts