hihoCoder#1114 小Hi小Ho的惊天大作战:扫雷·一
回溯+搜索
枚举每个位置上能否放地雷,当第i个位置枚举完成后,第i-1个位置的情况就确定了,此时,检查第i-1个位置是否满足要求,即左右间隔为1的范围内地雷数是否等于申明数字,如果满足条件,那么继续搜索下去,如果不满足条件,抛弃这个搜索分支。
搜索完成后,将所有可行解按位置“与”一下 ,找到那些一定为地雷或一定为空的格子。
最后输出即可。
代码:
1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 void merge(int *t, int *r, int n) { 7 for (int i = 0; i < n; i++) { 8 if (t[i] == -1 || t[i] == r[i]) 9 t[i] = r[i]; 10 else 11 t[i] = -2; 12 } 13 } 14 15 void find(int *a, int *r, int *t, int p, int n) { 16 if (p >= n) { 17 if ((n == 1 && a[p - 1] == r[p - 1]) 18 || ((n > 1) && a[p - 1] == r[p - 1] + r[p - 2])) 19 merge(t, r, n); 20 } 21 else if (p == 0) { 22 for (int i = 0; i < 2; i++) { 23 r[p] = i; 24 find(a, r, t, p + 1, n); 25 } 26 } 27 else if (p == 1) { 28 for (int i = 0; i < 2; i++) { 29 r[p] = i; 30 if (a[p - 1] == r[p - 1] + r[p]) 31 find(a, r, t, p + 1, n); 32 } 33 } 34 else { 35 for (int i = 0; i < 2; i++) { 36 r[p] = i; 37 if (a[p - 1] == r[p] + r[p - 1] + r[p - 2]) 38 find(a, r, t, p + 1, n); 39 } 40 } 41 } 42 43 int main() { 44 int n; 45 46 cin >> n; 47 while (n--) { 48 int N; 49 cin >> N; 50 int *a = new int[N]; 51 int *r = new int[N]; 52 int *t = new int[N]; 53 54 for (int i = 0; i < N; i++) 55 cin >> a[i]; 56 memset(r, 0, N * sizeof(int)); 57 memset(t, -1, N * sizeof(int)); 58 59 find(a, r, t, 0, N); 60 61 int mine = 0; 62 int not_mine = 0; 63 64 for (int i = 0; i < N; i++) { 65 mine += (t[i] == 1 ? 1 : 0); 66 not_mine += (t[i] == 0 ? 1 : 0); 67 } 68 69 cout << mine; 70 for (int i = 0; i < N; i++) 71 if (t[i] == 1) 72 cout << " " << i + 1; 73 cout << endl; 74 75 cout << not_mine; 76 for (int i = 0; i < N; i++) 77 if (t[i] == 0) 78 cout << " " << i + 1; 79 cout << endl; 80 81 delete t; 82 delete r; 83 delete a; 84 } 85 86 return 0; 87 }