hihoCoder#1120 小Hi小Ho的惊天大作战:扫雷·三
看上去非常复杂, 实际上是这一系列最简单的一步,本质上是个搜索过程,相比于前一道题,可以不用策略三,而且题目的数据规模超级小,所以暴力搜索就能过。
把尚未确定的点放在一个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的惊天大作战:扫雷·三的更多相关文章
- hihoCoder 1114 小Hi小Ho的惊天大作战:扫雷·一 最详细的解题报告
题目来源:小Hi小Ho的惊天大作战:扫雷·一 解题思路:因为只要确定了第一个是否有地雷就可以推算出后面是否有地雷(要么为0,要么为1,如果不是这两个值就说明这个方案行不通),如果两种可能中有一种成功, ...
- hiho #1114 : 小Hi小Ho的惊天大作战:扫雷·一
#1114 : 小Hi小Ho的惊天大作战:扫雷·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 故事背景:密室.监视器与充满危机的广场 “我们还是循序渐进,先来考虑这 ...
- hihoCoder#1119 小Hi小Ho的惊天大作战:扫雷·二
原题地址 没有复杂算法,就是麻烦,写起来细节比较多,比较考验细心,一次AC好开心. 代码: #include <iostream> #include <vector> #inc ...
- hihoCoder#1114 小Hi小Ho的惊天大作战:扫雷·一
原题地址 回溯+搜索 枚举每个位置上能否放地雷,当第i个位置枚举完成后,第i-1个位置的情况就确定了,此时,检查第i-1个位置是否满足要求,即左右间隔为1的范围内地雷数是否等于申明数字,如果满足条件, ...
- ACM学习历程—Hihocoder编程之美测试赛B题 大神与三位小伙伴(组合数学 )
时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 给你一个m x n (1 <= m, n <= 100)的矩阵A (0<=aij<=10000),要 ...
- 【转】HTML5的小知识点小集合
html5的小知识点小集合 html5知识 1. Doctype作用?标准模式与兼容模式各有什么区别? (1).<!DOCTYPE>声明位于位于HTML文档中的第一行,处于<h ...
- html5的小知识点小集合
html5的小知识点小集合 html5知识 1. Doctype作用?标准模式与兼容模式各有什么区别? (1).<!DOCTYPE>声明位于位于HTML文档中的第一行,处于< ...
- 微信小程序即将开放申请?微信小论坛小程序专场16日或可见分晓
9月22号微信小程序内测至今已经好一段时间了,首批只开放了200个名额,没拿到内测资格的朋友早就等到心急了.就在刚刚,微信公开课宣布微信小论坛小程序专场即将在11月16号举行,微信公众平台小程序会在当 ...
- 如何获取微信小店小程序的AppID
2017年11月16日,微信有一个重磅的宣布:为了帮商家在微信内快速开店,方便商家和用户之间沟通,所有认证公众号,可快速创建微信小店小程序.这个改变是否能给微信小店带来新的生机?还需要时间的考验.微信 ...
随机推荐
- Struts2 第三个程序 namespacce的用法
1.创建web项目,添加struts2支持的类库,在web.xml中配置struts2过滤器. 2.创建名为UserAction的Action对象,并分别在其中编写add()和update()方法,用 ...
- 442 Find All Duplicates in an Array 数组中重复的数据
给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次.找到所有出现两次的元素.你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗? ...
- Caused by: javax.el.PropertyNotFoundException: Property 'product' not found on type java.lang.String
今天在JSP利用EL表达式取值报了 "javax.el.PropertyNotFoundException”,经过debug和打印将问题定位到这段代码: HTML应该是没啥问题,看提示在ja ...
- 学习笔记 第十五章 JavaScript基础
第15章 JavaScript基础 [学习重点] 了解JavaScript基础知识 熟悉常量和变量 能够使用表达式和运算符 正确使用语句 能够掌握数据类型和转换的基本方法 正确使用函数.对象.数组 ...
- Elasticsearch--集群管理_再平衡&预热
目录 控制集群的再平衡 再平衡 集群的就绪 集群再平衡设置 控制再平衡何时开始 控制同时在节点移动的分片数量 控制单个节点上同时初始化的分片数量 控制单个节点上同时初始化的主分片数量 控制分配的分片类 ...
- Elasticsearch--集群&吞吐量
目录 高查询和高吞吐量 过滤器缓存 字段数据缓存和断路器 断路器 存储模块 索引缓冲和刷新率 索引刷新率 线程池的配置 一些通用的建议来配置高索引和查询吞吐量的集群 高查询和高吞吐量 过滤器缓存 过滤 ...
- openmv第一次调试
2018-09-19 20:14:51 import sensor, image, time import car import json import time from pyb import U ...
- tomcat 启动失败 和闪退 和 启动成功却没有页面显示
1.解压版tomcat 将tomcat解压至英文目录下, 在系统环境变量里面配置 JAVA_HOME 和CATALINA_HOME (就是tomcat的安装目录) 在path中配置 %CATALINA ...
- js添加千位分隔符
function thousandBitSeparator(num){ var re=/\d{1,3}(?=(\d{3})+$)/g; var n1=num.toString().replace(/^ ...
- laravel学习:容器绑定与解析
1.在服务容器中注册类(bind) $this->app->bind('sender','MailSender');//$this->app成为服务容器. 2.从服务容器生成类( ...