【题解】SCOI2009围豆豆
很久之前就很想做的一道题,一直思考到今天才下定决心看题解。这道题中,很关键的一点就在于:如何判断一个点是否在一个多边形内?其实如果计算几何基本功扎实的话,应该是可以很快给出答案的(可惜我完全不行):由一个点向一边引一条射线,判断与多边形相交的边数。若边数是奇数,说明在多边形的内部。在这里贴一篇博文:大佬的博客。
以下想图解一下射线法(与代码判图方式一致)。
1.图中五角星为一个豆豆。
2.在转移的时候,我们由\(f[i][j][k] -> f[i][j + 1][k']\) 的转移即为在这两个格子之间链接一条边界线。
3.再转移一下,我们会注意到此时这个豆豆向下引的射线与两条边界线均有交点,但它暂时是被包围的状态,与我们所设的状态矛盾。所以我们规定:只有与箭头头部相交才算做一次。
4.如果再次出现,次数变成偶数,就不在边界内了:
通过这几幅图,我们会发现竖直方向的移动不会改变豆豆是否被包围的判定,可以不必重复判断。了解了这一点之后,我们每一次的转移都是在画轮廓线。我们规定状态 \(f[i][j][k]\) 表示当前边界线画到第 \(\left ( i,j \right )\)时,被包围的豆豆状况为 \(k\) 时的最大得分。因为 \(\left ( i,j \right )\) 可以转移到 \(\left ( i,j + 1 \right )\),反之亦然,所以这个转移是不满足拓扑序的。但由于它满足三角形不等式,所以我们使用spfa来转移状态。由于题目规定移动会减少分数,所以不用担心存在正环的问题。
#include <bits/stdc++.h>
using namespace std;
#define maxn 20
#define maxk 6000
#define INF 99999999
int n, m, S, Map[maxn][maxn];
int ans, CNST, val[maxn];
int f[maxn][maxn][maxk];
const int dx[]={, , -, };
const int dy[]={-, , , };
bool vis[maxn][maxn][maxk]; struct node
{
int x, y, num;
node(int xx = , int yy = , int zz = ) { x = xx, y = yy, num = zz; }
}; queue <node> q;
node p[maxn]; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} void spfa(int sx, int sy)
{
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
for(int k = ; k < CNST; k ++)
f[i][j][k] = -INF;
q.push(node(sx, sy, )), f[sx][sy][] = , vis[sx][sy][] = ;
while(!q.empty())
{
node now = q.front(); q.pop();
vis[now.x][now.y][now.num] = ;
if(now.x == sx && now.y == sy)
ans = max(ans, f[now.x][now.y][now.num]);
for(int k = ; k < ; k ++)
{
int xx = now.x + dx[k], yy = now.y + dy[k];
if(xx <= || xx > n || yy <= || yy > m || Map[now.x][now.y]) continue;
int num = now.num, Y = max(yy, now.y), del = ;
if(k <= )
{
for(int i = ; i <= S; i ++)
if(p[i].y == Y && p[i].x < xx)
{
num ^= << (i - );
if((num >> i - ) & ) del += val[i];
else del -= val[i];
}
}
if(f[xx][yy][num] < f[now.x][now.y][now.num] + del - )
{
f[xx][yy][num] = f[now.x][now.y][now.num] + del - ;
if(!vis[xx][yy][num]) vis[xx][yy][num] = , q.push(node(xx, yy, num));
}
}
}
} int main()
{
n = read(), m = read(), S = read();
CNST = ( << S) - ;
for(int i = ; i <= S; i ++) val[i] = read();
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
{
char c; cin >> c;
if(c == '#') Map[i][j] = -;
else Map[i][j] = c - '';
if(Map[i][j] >= ) p[Map[i][j]] = node(i, j);
}
for(int i = ; i <= n; i ++)
for(int j = ; j <= m; j ++)
if(!Map[i][j]) spfa(i, j);
printf("%d\n", ans);
return ;
}
【题解】SCOI2009围豆豆的更多相关文章
- 【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)
题目传送门 题解 Σ(っ °Д °;)っ 前置知识 射线法:从一点向右(其实哪边都行)水平引一条射线,若射线与路径的交点为偶数,则点不被包含,若为奇数,则被包含.(但注意存在射线与路径重合的情况) 这 ...
- BZOJ1294: [SCOI2009]围豆豆Bean
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1294 状压dp,dis[s][i][j]表示从(i,j)出发围的状态是s的最短路. 然后判断一 ...
- [SCOI2009]围豆豆
Description Input 第一行两个整数N和M,为矩阵的边长. 第二行一个整数D,为豆子的总个数. 第三行包含D个整数V1到VD,分别为每颗豆子的分值. 接着N行有一个N×M的字符矩阵来描述 ...
- 【BZOJ】1294: [SCOI2009]围豆豆Bean
题解 随机跳题真好玩 这个就是考虑我们怎么判断点在多边形内,就是点做一条射线,穿过了奇数条边 我们只需要记录一个二进制状态表示每个点的射线穿过路径的次数的奇偶性 枚举起点,然后用BFS的方式更新dp状 ...
- 洛谷P2566 [SCOI2009]围豆豆(状压dp+计算几何)
题面 传送门 题解 首先要解决一个问题,就是怎么判断一个点是否在多边形内部 从这个点向某一个方向做一条射线,如果这条射线和多边形的交点为奇数说明在多边形内,否则在多边形外 然而有一些特殊情况,比方说一 ...
- BZOJ 1294 [SCOI2009]围豆豆Bean ——计算几何
显然我们不可能表示出一台路径,因为实在是太复杂了. 所以我们可以记录一下路径对答案的影响,显然路径对答案影响相同的时候,答案更优,所以我们可以用影响来代替路径. 所以我们考虑状压一下所有的豆子有没有被 ...
随机推荐
- 浅谈localStorage的用法
今天接到一个任务,说是让自动调节textarea标记的输入高度,而且还要记录下来,下次登录的时候还是调节后的高度,我第一时间就想到了localStorage的用法,直接代码献上: <html l ...
- ethereum(以太坊)(基础)--容易忽略的坑(一)
pragma solidity ^0.4.0; contract base{ address public _owner=msg.sender; uint _a; string internal _b ...
- YII2 多MongoDB配置和使用
1:在config/web.php 文件下配置多个连接即可: 注意在componets 下 'mongodb' => [ 'class' => '\yii\mongodb\Connecti ...
- Hadoop(20)-MapReduce框架原理-OutputFormat
1.outputFormat接口实现类 2.自定义outputFormat 步骤: 1). 定义一个类继承FileOutputFormat 2). 定义一个类继承RecordWrite,重写write ...
- centos编译安装rabbitmq
安装环境 [root@VM_12_50_centos rabbitmq]# uname -a Linux VM_12_50_centos 3.10.0-514.21.1.el7.x86_64 #1 S ...
- PHP教程专题资源免费下载地址收藏
PHP教程专题资源免费下载地址收藏 PHP,即Hypertext Preprocessor,是一种被广泛应用的开源通用脚本语言,尤其适用于 Web 开发并可嵌入 HTML 中去.它的语法利用了 C. ...
- Intellij 出现“Usage of API documented as @since 1.4+”的解决办法
https://blog.csdn.net/wust_lh/article/details/73277185
- python2.7练习小例子(二十八)
28):题目:请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续判断第二个字母. 程序分析:用情况语句比较好,如果第一个字母一样,则判断用情况语句或if语句判断第二个字母. ...
- WCF入门四[WCF的通信模式]
一.概述 WCF的通信模式有三种:请求/响应模式.单向模式和双工通信. 二.请求/响应模式 请求/响应模式就是WCF的默认模式,前面几篇随笔中的示例都是这种模式,当客户端发送请求后(非异步状态下),即 ...
- Spring AOP(一)——基础概念
前文的一些内容更多是针对Spring容器内部的一些特性的描述,接下来一个专题将描述Spring AOP的一些信息,配置细节等等. 介绍 面向切面编程(AOP)是一种新的针对程序结构的思路,它补足了面向 ...