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日,微信有一个重磅的宣布:为了帮商家在微信内快速开店,方便商家和用户之间沟通,所有认证公众号,可快速创建微信小店小程序.这个改变是否能给微信小店带来新的生机?还需要时间的考验.微信 ...
随机推荐
- New Year Tree CodeForces -620E
这个题有一个技巧:把颜色压到一个long long 上. #include<cstdio> #include<algorithm> #include<cstring> ...
- Ignatius and the Princess III HDU - 1028 || 整数拆分,母函数
Ignatius and the Princess III HDU - 1028 整数划分问题 假的dp(复杂度不对) #include<cstdio> #include<cstri ...
- 找规律 UVALive 6506 Padovan Sequence
题目传送门 /* 找规律:看看前10项就能看出规律,打个表就行了.被lld坑了一次:( */ #include <cstdio> #include <algorithm> #i ...
- 关于java的arrays数组排序示例AJPFX的分享
Java API对Arrays类的说明是:此类包含用来操作数组(比如排序和搜索)的各种方法. 1.对基本数据类型的数组的排序 说明: (1)Arrays类中的sort()使用的是“经过调优的快速排序法 ...
- 掌握Spark机器学习库(课程目录)
第1章 初识机器学习 在本章中将带领大家概要了解什么是机器学习.机器学习在当前有哪些典型应用.机器学习的核心思想.常用的框架有哪些,该如何进行选型等相关问题. 1-1 导学 1-2 机器学习概述 1- ...
- Python学习 Day 4 函数 切片 迭代 列表生成式 生成器
定义函数 def my_abs(x):#求绝对值的my_abs函数 if x >= 0: return x else: return –x def nop():#空函数 pass#占位符 参数检 ...
- Win7系统32位和64位的区别
Win7系统32位和64位的区别已经是一个老话题了,可是还是有很多朋友不明白.这两者到底有什么区别呢?下面本文与大家通俗的介绍下Win7系统32位和64位的区别,其他一些深入的理论讲述,大家可以看看文 ...
- Winform之GDI绘制验证码
主要功能:点击验证码可更换,输入验证码进行登陆 需要导入命名空间System.Drawing; 产生五位的随机字符串: 1 Random random = new Random(); //产生5个随机 ...
- OpenMP入门教程(一)
什么是OpenMP Open Multi-Processing的缩写,是一个应用程序接口(API),可用于显式指导多线程.共享内存的并行性. 在项目程序已经完成好的情况下不需要大幅度的修改源代码,只需 ...
- WPF知识点--自定义Button(ControlTemplate控件模板)
ControlTemplate是一种控件模板,可以通过它自定义一个模板来替换掉控件的默认模板以便打造个性化的控件. ControlTemplate包含两个重要的属性:VisualTree 该模板的视觉 ...