BZOJ 1294 围豆豆 题解
题目
是不是平时在手机里玩吃豆豆游戏玩腻了呢?最近MOKIA手机上推出了一种新的围豆豆游戏,大家一起来试一试吧。
游戏的规则非常简单,在一个N×M的矩阵方格内分布着D颗豆子,每颗豆有不同的分值Vi。游戏者可以选择任意一个方格作为起始格,每次移动可以随意的走到相邻的四个格子,直到最终又回到起始格。最终游戏者的得分为所有被路径围住的豆豆的分值总和减去游戏者移动的步数。矩阵中某些格子内设有障碍物,任何时刻游戏者不能进入包含障碍物或豆子的格子。游戏者可能的最低得分为0,即什么都不做。
注意路径包围的概念,即某一颗豆在路径所形成的多边形(可能是含自交的复杂多边形)的内部。下面有两个例子:
第一个例子中,豆在路径围成的矩形内部,所以豆被围住了。第二个例子中,虽然路径经过了豆的周围的8个格子,但是路径形成的多边形内部并不包含豆,所以没有围住豆子。
布布最近迷上了这款游戏,但是怎么玩都拿不了高分。聪明的你决定写一个程序来帮助他顺利通关。
输入格式
第一行两个整数\(N\)和\(M\),为矩阵的边长。
第二行一个整数\(D\),为豆子的总个数。
第三行包含\(D\)个整数\(V_1\)到\(V_D\),分别为每颗豆子的分值。
接着\(N\)行有一个\(N \times M\)的字符矩阵来描述游戏矩阵状态,0
表示空格,#
表示障碍物。而数字1
到9
分别表示对应编号的豆子。
输出格式
仅包含一个整数,为最高可能获得的分值。
样例输入
3 8
3
30 -100 30
00000000
010203#0
00000000
样例输出
38
说明/提示
50%的数据满足\(1 \le D \le 3\)。
100%的数据满足\(1 \le D \le 9,1 \le N, M \le 10,-10000 \le V_i \le 10000\)。
题解
\(N,M\)的范围都很小,所以可以直接暴力广搜,但是保存状态不能直接用数组,处理起来会很麻烦,应该状态压缩.
我重点讲一下怎么判断一个点是否在多边形内:
先说结论,从某点向外做射线,若该射线与多边形相交了奇数次,该点就在该多边形的内部,否则在外部
下面证明
我们设想这个射线是从这个点出发的一条路径,在我们沿着这个路径走的过程中,可以得到以下结论:
由于射线无限长,而多边形有限,所以射线最后一次与多边形相交一定是从多边形内部交到外部,由此可得,倒数第二次相交(如果有的话)一定是从外部交到内部.
所以每交一次内外状态翻转,而最后的状态又是在外部,所以当交奇数次,最开始状态和最后的状态相反,即在内部,同理当交偶数次,最开始在外部.
这道题中规定从该点向右的射线为判定线,当你搜索路径奇数次相交于点\(i\)的判定线,点\(i\)在路径多边形内部,反之在外部.
当这个点的状态从在外部变成在内部,总分数加上这个点的分值;当这个点的状态从在内部变成在外部,总分数减去这个点的分值,注意搜索过程中每走一步总分值要减一.
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 15, M = 1050;
int n, m, d, f[N][N][M], vis[N][N], in[N][N][M], x[N], y[N], bean[N], ans, dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
struct node {int x, y, status;};
queue<node> q;
void solve(int fx, int fy) {
memset(f, 0, sizeof(f)), memset(in, 0, sizeof(in));
f[fx][fy][0] = 0, q.push((node){fx, fy, 0});
while (!q.empty()) {
node now = q.front();
q.pop();
for (int k = 0; k < 4; k++) {
int nx = now.x + dx[k], ny = now.y + dy[k];
if (nx <= 0 || nx > n || ny <= 0 || ny > m || vis[nx][ny]) continue;
int status = now.status, score = f[now.x][now.y][now.status] - 1; // 注意减去移动的1步
if (k < 2) { // k<2时,上下移动才可能穿过右射线
for (int i = 1; i <= d; i++) { //枚举豆子
if (x[i] != min(nx, now.x) || y[i] > ny) continue; //没穿过这个豆子的右射线 or 经过这个豆子的左边
if (status >> i - 1 & 1) score -= bean[i];
else score += bean[i];
status ^= (1 << (i - 1)); //改变经过次数奇偶性
}
}
if (!in[nx][ny][status])
in[nx][ny][status]=1, f[nx][ny][status] = score, q.push((node){nx, ny, status});
}
}
for (int i = 0; i < (1 << d); i++)
if (in[fx][fy][i]) ans = max(ans, f[fx][fy][i]);
}
int main() {
scanf("%d%d%d", &n, &m, &d);
for (int i = 1; i <= d; i++) scanf("%d", &bean[i]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
char c;
scanf(" %c", &c);
if (c == '#') vis[i][j] = -1;
else x[c - '0'] = i, y[c - '0'] = j, vis[i][j] = c - '0';
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (!vis[i][j]) solve(i, j);
printf("%d\n", ans);
return 0;
}
BZOJ 1294 围豆豆 题解的更多相关文章
- 【BZOJ1294】[SCOI2009]围豆豆(动态规划,状压)
[BZOJ1294][SCOI2009]围豆豆(动态规划,状压) 题面 BZOJ 洛谷 题解 首先考虑如何判断一个点是否在一个多边形内(不一定是凸的),我们从这个点开始,朝着一个方向画一条射线,看看它 ...
- 【BZOJ1294】[SCOI2009]围豆豆Bean 射线法+状压DP+SPFA
[BZOJ1294][SCOI2009]围豆豆Bean Description Input 第一行两个整数N和M,为矩阵的边长. 第二行一个整数D,为豆子的总个数. 第三行包含D个整数V1到VD,分别 ...
- [BZOJ1294][SCOI2009]围豆豆Bean 射线法+状压dp+spfa
1294: [SCOI2009]围豆豆Bean Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 458 Solved: 305[Submit][Sta ...
- 洛谷P2566 [SCOI2009]围豆豆(状压dp+spfa)
题目传送门 题解 Σ(っ °Д °;)っ 前置知识 射线法:从一点向右(其实哪边都行)水平引一条射线,若射线与路径的交点为偶数,则点不被包含,若为奇数,则被包含.(但注意存在射线与路径重合的情况) 这 ...
- BZOJ 1003 物流运输 题解 【SPFA+DP】
BZOJ 1003 物流运输 题解 Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的 ...
- BZOJ 1191 超级英雄 Hero 题解
BZOJ 1191 超级英雄 Hero 题解 Description 现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的多少获得不同数目的奖品或奖金 ...
- SCOI 2009 围豆豆(状压DP)
SCOI 2009 围豆豆 题目描述 是不是平时在手机里玩吃豆豆游戏玩腻了呢?最近MOKIA手机上推出了一种新的围豆豆游戏,大家一起来试一试吧. 游戏的规则非常简单,在一个N×M的矩阵方格内分布着D颗 ...
- BZOJ1294 洛谷P2566 状态压缩DP 围豆豆
传送门 题目描述 是不是平时在手机里玩吃豆豆游戏玩腻了呢?最近MOKIA手机上推出了一种新的围豆豆游戏,大家一起来试一试吧游戏的规则非常简单,在一个N×M的矩阵方格内分布着D颗豆子,每颗豆有不同的分值 ...
- 【BZOJ】1294: [SCOI2009]围豆豆Bean
题解 随机跳题真好玩 这个就是考虑我们怎么判断点在多边形内,就是点做一条射线,穿过了奇数条边 我们只需要记录一个二进制状态表示每个点的射线穿过路径的次数的奇偶性 枚举起点,然后用BFS的方式更新dp状 ...
随机推荐
- java作品集:企业信息门户webtap
作品背景 随着企业应用的软件越来越多,并且信息软件基本以B/S为主了,很多时候各种软件的地址,让大家记的头昏脑胀,并且一堆密码要记,而且大部分系统之间无法互通,虽然市面上有各种集成方案,但无法做到简单 ...
- k8s学习-资源控制器
4.3.资源控制器 4.3.1.概念 Kubernetes中内建了很多种controller(控制器),这些相当于一个状态机,用来控制Pod的具体状态和行为. 4.3.2.分类 Replication ...
- shell编程(一):功能、执行、基础
1.shell的功能 (1)自动化批量初始化系统:对N台系统初始化(装系统时对系统的时区.yum源.软件包的更新.安全的设置进行初始化) (2)自动化批量部署软件程序:(LAMP/LNMP/Tomca ...
- vs2010静态编译qt5.1.0
本博文参考 http://blog.chinaunix.net/uid-20690340-id-3802197.html 静态库在链接的时候直接写入二进制文件里,这样的好处在于发布的时候无需附带dll ...
- Vue —— 精讲 VueRouter(1)
最近被Boos调去给新人做培训去了,目前把自己整理的一些东西分享出来,希望对大家有所帮助 本章节为VueRouter前端 路由的章节部分 大纲 一.基本概念 路由就是通过网络把讯息从源地址传输到目的地 ...
- Largest Rectangle in a Histogram【单调栈模板】
Largest Rectangle in a Histogram 题目链接(点击)来源poj 2559 A histogram is a polygon composed of a sequence ...
- selenium获取图片验证码
# encoding:utf-8 from PIL import Image from selenium import webdriver url = '网站地址' driver = webdrive ...
- ZWave对COMAND CLASS的处理流程
文章主题 在开发一个 ZWave Device 的过程中,对 COMAND CLASS(单词太长了,后面就简写为 CC 啦) 的处理是最基本.最重要的工作.这篇文章以最最简单的 CC:COMMNAD ...
- numpy中np.array()与np.asarray的区别以及.tolist
array 和 asarray 都可以将 结构数据 转化为 ndarray,但是主要区别就是当数据源是ndarray时,array仍然会copy出一个副本,占用新的内存,但asarray不会. 1.输 ...
- springboot 2.X 集成redis
在实际开发中,经常会引入redis中间件做缓存,这里介绍springboot2.X后如何配置redis 1 Maven中引入redis springboot官方通过spring-boot-autoco ...