原题地址

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

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

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

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

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

代码:

 #include <iostream>
#include <vector>
#include <cstring>
#include <cstdlib> using namespace std; struct point {
int r;
int c;
int v;
point(int _r, int _c) : r(_r), c(_c) {};
point(int _r, int _c, int _v) : r(_r), c(_c), v(_v) {};
bool operator==(const point &o) {return o.r == r && o.c == c;}
bool operator!=(const point &o) {return o.r != r || o.c != c;}
}; #define SIZE 40 int N, M;
int field[SIZE][SIZE];
int ans[SIZE][SIZE];
int unset[SIZE][SIZE];
vector<point> unsettled; bool valid(point &p) {
return p.r >= && p.r < N && p.c >= && p.c < M;
} vector<point> neighbors(point p) {
vector<point> res; for (int i = -; i < ; i++) {
for (int j = -; j < ; j++) {
point q(i + p.r, j + p.c);
if (valid(q) && q != p)
res.push_back(q);
}
} return res;
} void merge(point p) {
if (ans[p.r][p.c] == - || ans[p.r][p.c] == p.v)
ans[p.r][p.c] = p.v;
else
ans[p.r][p.c] = -;
} int around(point p, int s) {
vector<point> nbs = neighbors(p);
int res = ; for (auto q : nbs) {
if (field[q.r][q.c] >= && s == ) {
res++;
continue;
}
else
res += unset[q.r][q.c] == s ? : ;
} return res;
} bool check(point p) {
vector<point> nbs = neighbors(p);
int mine = around(p, );
int not_mine = around(p, );
return (mine <= field[p.r][p.c] && field[p.r][p.c] + not_mine <= nbs.size());
} bool check() {
bool is_ok = true; for (auto p : unsettled) {
if (!is_ok)
break;
vector<point> nbs = neighbors(p);
for (auto q : nbs) {
if (field[q.r][q.c] >= && !check(q)) {
is_ok = false;
break;
}
}
} return is_ok;
} void extend() {
bool over = false; while (!over) {
over = true;
for (auto p : unsettled) {
vector<point> nbs = neighbors(p);
for (auto q : nbs) {
if (field[q.r][q.c] < )
continue; vector<point> os = neighbors(q);
int mine = around(p, );
int not_mine = around(q, ); if (field[q.r][q.c] + not_mine == os.size()) {
for (auto o : os) {
if (o.v == -) {
over = false;
o.v = ;
unset[o.r][o.c] = ;
}
}
}
if (mine == field[q.r][q.c]) {
for (auto o : os) {
if (o.v == -) {
over = false;
o.v = ;
unset[o.r][o.c] = ;
}
}
}
}
}
}
} void solve(int pos) {
if (pos >= unsettled.size()) {
for (auto p : unsettled) {
merge(p);
}
return;
} if (unsettled[pos].v != -) {
solve(pos + );
unsettled[pos].v = -;
unset[unsettled[pos].r][unsettled[pos].c] = -;
return;
} for (int i = ; i < ; i++) {
unsettled[pos].v = i;
unset[unsettled[pos].r][unsettled[pos].c] = i;
if (!check())
continue;
extend();
solve(pos + );
}
unsettled[pos].v = -;
unset[unsettled[pos].r][unsettled[pos].c] = -;
} int main() {
int n; cin >> n;
while (n--) {
cin >> N >> M;
memset(ans, -, SIZE * SIZE * sizeof(int));
memset(unset, -, SIZE * SIZE * sizeof(int));
unsettled.clear();
for (int i = ; i < N; i++) {
for (int j = ; j < M; j++) {
cin >> field[i][j];
if (field[i][j] < )
unsettled.push_back(point(i, j, -));
}
} solve(); int mine = ;
int not_mine = ; for (auto p : unsettled) {
mine += (ans[p.r][p.c] == ? : );
not_mine += (ans[p.r][p.c] == ? : );
} cout << mine << " " << not_mine << endl; } return ;
}

hihoCoder#1120 小Hi小Ho的惊天大作战:扫雷·三的更多相关文章

  1. hihoCoder 1114 小Hi小Ho的惊天大作战:扫雷·一 最详细的解题报告

    题目来源:小Hi小Ho的惊天大作战:扫雷·一 解题思路:因为只要确定了第一个是否有地雷就可以推算出后面是否有地雷(要么为0,要么为1,如果不是这两个值就说明这个方案行不通),如果两种可能中有一种成功, ...

  2. hiho #1114 : 小Hi小Ho的惊天大作战:扫雷·一

    #1114 : 小Hi小Ho的惊天大作战:扫雷·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 故事背景:密室.监视器与充满危机的广场 “我们还是循序渐进,先来考虑这 ...

  3. hihoCoder#1119 小Hi小Ho的惊天大作战:扫雷·二

    原题地址 没有复杂算法,就是麻烦,写起来细节比较多,比较考验细心,一次AC好开心. 代码: #include <iostream> #include <vector> #inc ...

  4. hihoCoder#1114 小Hi小Ho的惊天大作战:扫雷·一

    原题地址 回溯+搜索 枚举每个位置上能否放地雷,当第i个位置枚举完成后,第i-1个位置的情况就确定了,此时,检查第i-1个位置是否满足要求,即左右间隔为1的范围内地雷数是否等于申明数字,如果满足条件, ...

  5. ACM学习历程—Hihocoder编程之美测试赛B题 大神与三位小伙伴(组合数学 )

    时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给你一个m x n (1 <= m, n <= 100)的矩阵A (0<=aij<=10000),要 ...

  6. 【转】HTML5的小知识点小集合

    html5的小知识点小集合 html5知识   1.  Doctype作用?标准模式与兼容模式各有什么区别? (1).<!DOCTYPE>声明位于位于HTML文档中的第一行,处于<h ...

  7. html5的小知识点小集合

      html5的小知识点小集合 html5知识   1.  Doctype作用?标准模式与兼容模式各有什么区别? (1).<!DOCTYPE>声明位于位于HTML文档中的第一行,处于< ...

  8. 微信小程序即将开放申请?微信小论坛小程序专场16日或可见分晓

    9月22号微信小程序内测至今已经好一段时间了,首批只开放了200个名额,没拿到内测资格的朋友早就等到心急了.就在刚刚,微信公开课宣布微信小论坛小程序专场即将在11月16号举行,微信公众平台小程序会在当 ...

  9. 如何获取微信小店小程序的AppID

    2017年11月16日,微信有一个重磅的宣布:为了帮商家在微信内快速开店,方便商家和用户之间沟通,所有认证公众号,可快速创建微信小店小程序.这个改变是否能给微信小店带来新的生机?还需要时间的考验.微信 ...

随机推荐

  1. Struts2 第三个程序 namespacce的用法

    1.创建web项目,添加struts2支持的类库,在web.xml中配置struts2过滤器. 2.创建名为UserAction的Action对象,并分别在其中编写add()和update()方法,用 ...

  2. 442 Find All Duplicates in an Array 数组中重复的数据

    给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次.找到所有出现两次的元素.你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗? ...

  3. Caused by: javax.el.PropertyNotFoundException: Property 'product' not found on type java.lang.String

    今天在JSP利用EL表达式取值报了 "javax.el.PropertyNotFoundException”,经过debug和打印将问题定位到这段代码: HTML应该是没啥问题,看提示在ja ...

  4. 学习笔记 第十五章 JavaScript基础

    第15章   JavaScript基础 [学习重点] 了解JavaScript基础知识 熟悉常量和变量 能够使用表达式和运算符 正确使用语句 能够掌握数据类型和转换的基本方法 正确使用函数.对象.数组 ...

  5. Elasticsearch--集群管理_再平衡&预热

    目录 控制集群的再平衡 再平衡 集群的就绪 集群再平衡设置 控制再平衡何时开始 控制同时在节点移动的分片数量 控制单个节点上同时初始化的分片数量 控制单个节点上同时初始化的主分片数量 控制分配的分片类 ...

  6. Elasticsearch--集群&吞吐量

    目录 高查询和高吞吐量 过滤器缓存 字段数据缓存和断路器 断路器 存储模块 索引缓冲和刷新率 索引刷新率 线程池的配置 一些通用的建议来配置高索引和查询吞吐量的集群 高查询和高吞吐量 过滤器缓存 过滤 ...

  7. openmv第一次调试

    2018-09-19  20:14:51 import sensor, image, time import car import json import time from pyb import U ...

  8. tomcat 启动失败 和闪退 和 启动成功却没有页面显示

    1.解压版tomcat 将tomcat解压至英文目录下, 在系统环境变量里面配置 JAVA_HOME 和CATALINA_HOME (就是tomcat的安装目录) 在path中配置 %CATALINA ...

  9. js添加千位分隔符

    function thousandBitSeparator(num){ var re=/\d{1,3}(?=(\d{3})+$)/g; var n1=num.toString().replace(/^ ...

  10. laravel学习:容器绑定与解析

    1.在服务容器中注册类(bind) $this->app->bind('sender','MailSender');//$this->app成为服务容器.   2.从服务容器生成类( ...