hihoCoder#1120 小Hi小Ho的惊天大作战:扫雷·三

原题地址

 

看上去非常复杂, 实际上是这一系列最简单的一步,本质上是个搜索过程,相比于前一道题,可以不用策略三,而且题目的数据规模超级小,所以暴力搜索就能过。

把尚未确定的点放在一个unsettled列表里,然后依次枚举每个点的情况:是地雷or不是地雷

优化方案一即:每次枚举后,使用规则一、规则二对列表里剩下的点进行判断,如果能直接判断出是不是地雷的就立即设置了,这样剩下的枚举位就少了。当然回溯的时候记得把这些拓展出来的也要一并回溯。

优化方案二即:周围已知地雷数少的点优先枚举。(这个优化没做)

 

啰啰嗦嗦写了一大堆代码,WA了一次,原来是判断规则一规则二的时候单纯用8去做判断了,而一个点周围邻居点个数可能不是8。

代码:

  1 #include <iostream>

  2 #include <vector>

  3 #include <cstring>

  4 #include <cstdlib>

  5 

  6 using namespace std;

  7 

  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 }

 

你可能感兴趣的:(code)