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日,微信有一个重磅的宣布:为了帮商家在微信内快速开店,方便商家和用户之间沟通,所有认证公众号,可快速创建微信小店小程序.这个改变是否能给微信小店带来新的生机?还需要时间的考验.微信 ...
随机推荐
- 题解报告:poj 1195 Mobile phones(二维BIT裸题)
Description Suppose that the fourth generation mobile phone base stations in the Tampere area operat ...
- 转 PHP Cookies
cookie 常用于识别用户. 什么是 Cookie? cookie 常用于识别用户.cookie 是服务器留在用户计算机中的小文件.每当相同的计算机通过浏览器请求页面时,它同时会发送 cookie. ...
- JS 事件添加onclick写法注意。
自定义函数添加onclick事件写法注意. 错误写法:element.onclick = addclass(className); 正确写法:element.onclick = function(){ ...
- AJPFX关于网络编程的理解
1:网络编程(理解) (1)网络编程:用Java语言实现计算机间数据的信息传递和资源共享 (2)网络编程模型 (3)网络编程的三要素 ...
- Jboss服务器使用
一.作者前言 早上坐地铁的时候,阅览about JAVA.了解到一个程序猿,对于服务器的使用,最起码的熟悉那么几种,例如tomcat,jboss,weblogic,websphere,还有Nginx. ...
- 我用 Python 爬了智联“北上广深”5400条 Java 招聘数据
结论 国际惯例,先上结论. Java 类职位招聘,不论是需求量(工作机会),还是工资平均水平,都是帝都北京最好. 北京和上海的平均工资差距不大(不超过200/月),但上海的需求量是北京的一半,机会更少 ...
- windows上把git生成的ssh key
右键鼠标,选中 “Git Bash here”: 输入指令,创建ssh key: cd ~/.ssh/ #bash: cd: /c/Users/Administrator/.ssh/: No such ...
- php接收json格式数据(text/xml)
在API服务中,目前流行采用json形式来交互. 给前端调用的接口输出Json数据,这个比较简单,只需要组织好数据,用json_encode($array) 转化一下,前端就得到json格式的数据. ...
- BotFramework学习-02
1.请求的Message格式 { "type": "Message", "id": "fd89606f8014453ca5587e ...
- Zed Shaw:程序员的常见健康问题
Zed Shaw:程序员的常见健康问题 原文作者Zed Shaws是一位作家.软件开发人员.音乐人(下文中提到吉他手),于2010年发布<Learn Python The Hard Way> ...