很久之前就很想做的一道题,一直思考到今天才下定决心看题解。这道题中,很关键的一点就在于:如何判断一个点是否在一个多边形内?其实如果计算几何基本功扎实的话,应该是可以很快给出答案的(可惜我完全不行):由一个点向一边引一条射线,判断与多边形相交的边数。若边数是奇数,说明在多边形的内部。在这里贴一篇博文:大佬的博客。

  以下想图解一下射线法(与代码判图方式一致)。

  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[4]={0, 0, -1, 1};
const int dy[4]={-1, 1, 0, 0};
bool vis[maxn][maxn][maxk];struct node
{int x, y, num;node(int xx = 0, int yy = 0, int zz = 0) { x = xx, y = yy, num = zz; }
}; queue <node> q;
node p[maxn];int read()
{int x = 0, k = 1;char c;c = getchar();while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();return x * k;
}void spfa(int sx, int sy)
{for(int i = 1; i <= n; i ++)for(int j = 1; j <= m; j ++)for(int k = 0; k < CNST; k ++)f[i][j][k] = -INF;q.push(node(sx, sy, 0)), f[sx][sy][0] = 0, vis[sx][sy][0] = 1;while(!q.empty()){node now = q.front(); q.pop();vis[now.x][now.y][now.num] = 0;if(now.x == sx && now.y == sy)ans = max(ans, f[now.x][now.y][now.num]);for(int k = 0; k < 4; k ++){int xx = now.x + dx[k], yy = now.y + dy[k];if(xx <= 0 || xx > n || yy <= 0 || yy > m || Map[now.x][now.y]) continue;int num = now.num, Y = max(yy, now.y), del = 0;if(k <= 1){for(int i = 1; i <= S; i ++)if(p[i].y == Y && p[i].x < xx) {num ^= 1 << (i - 1);if((num >> i - 1) & 1) del += val[i];else del -= val[i];}}if(f[xx][yy][num] < f[now.x][now.y][now.num] + del - 1){f[xx][yy][num] = f[now.x][now.y][now.num] + del - 1;if(!vis[xx][yy][num]) vis[xx][yy][num] = 1, q.push(node(xx, yy, num));}}}
}int main()
{n = read(), m = read(), S = read();CNST = (1 << S) - 1;for(int i = 1; i <= S; i ++) val[i] = read();for(int i = 1; i <= n; i ++)for(int j = 1; j <= m; j ++){char c; cin >> c;if(c == '#') Map[i][j] = -1;else Map[i][j] = c - '0';if(Map[i][j] >= 1) p[Map[i][j]] = node(i, j);}for(int i = 1; i <= n; i ++)for(int j = 1; j <= m; j ++)if(!Map[i][j]) spfa(i, j);printf("%d\n", ans);return 0;
} 

转载于:https://www.cnblogs.com/twilight-sx/p/9122212.html

【题解】SCOI2009围豆豆相关推荐

  1. 【BZOJ1294】[SCOI2009]围豆豆(动态规划,状压)

    [BZOJ1294][SCOI2009]围豆豆(动态规划,状压) 题面 BZOJ 洛谷 题解 首先考虑如何判断一个点是否在一个多边形内(不一定是凸的),我们从这个点开始,朝着一个方向画一条射线,看看它 ...

  2. 【做题记录】[SCOI2009]围豆豆

    [SCOI2009]围豆豆 \(n\times m(n,m\le 10)\) 的网格中有 \(d\) 个球 \((d\le 9)\),要求在网格中选定一个起点开始做一个欧拉回路,路径的价值为路径完全包 ...

  3. 洛谷P2566 [SCOI2009]围豆豆(状压dp+计算几何)

    题面 传送门 题解 首先要解决一个问题,就是怎么判断一个点是否在多边形内部 从这个点向某一个方向做一条射线,如果这条射线和多边形的交点为奇数说明在多边形内,否则在多边形外 然而有一些特殊情况,比方说一 ...

  4. 退役前的做题记录2.0

    退役前的做题记录2.0 最近在刷省选题......大致上是按照省份刷的. 不过上面的题目顺序是按照写题的顺序排列的,所以可能会有点乱哈. [BZOJ2823][AHOI2012]信号塔 最小圆覆盖,随 ...

  5. [颓废史]蒟蒻的刷题记录

    QAQ蒟蒻一枚,其实我就是来提供水题库的. 以下记录从2016年开始. 1.1 1227: [SDOI2009]虔诚的墓主人 树状数组+离散化 3132: 上帝造题的七分钟 树状数组 二维区间加减+查 ...

  6. 2019 CCPC Wannafly Camp Day 1

    自闭感受 第一次参加这种线下的算法Camp,不得不说和队友都是内心非常的小鸡动.上午开幕式wls讲了一堆话,差不多就是一起呲逼加鸡汤吧 (哈哈希望wls不要打死我) .下午就是day训练赛了,因为一个 ...

  7. [SCOI2009]迷路 题解

    [SCOI2009]迷路 [SCOI2009]迷路 文章目录 思考过程 题解 思考过程 这个东西发现距离只有 999,记得 Lcm(1-9)=2520\tt Lcm(1 \dots 9) = 2520 ...

  8. 【题解】P4158 [SCOI2009]粉刷匠(DP,背包)

    [题解]P4158 [SCOI2009]粉刷匠 是一道资源规划 DP 的好题,但是我想了很久还去看了题解./kk我真菜. 题目链接 P4158 [SCOI2009]粉刷匠 - 洛谷 题意概述 发现自己 ...

  9. 题解 BZOJ1026 luogu P2657 [SCOI2009]windy数 数位DP

    BZOJ & luogu 看到某大佬AC,本蒟蒻也决定学习一下玄学的数位$dp$ (以上是今年3月写的话(叫我鸽神$qwq$)) 思路:数位$DP$ 提交:2次 题解:(见代码) #inclu ...

最新文章

  1. BP神经网络预测实例
  2. 关于mysql的ddl_log.log文件
  3. 新基建7大产业链约500家企业图谱!
  4. CSS手写代码总结02
  5. java8方法引用符合_java8,方法引用
  6. 提取javadoc_使用JavaParser从源文件中提取JavaDoc文档
  7. 000 SpringMVC介绍
  8. Java内存模型常见问题
  9. 计算机未来发展的5个前景,学习成绩普通,高考志愿填报不妨考虑这5个专业,未来发展很不错...
  10. 轻量级 HTTP(s) 代理 TinyProxy
  11. 海量运维、运营规划之道
  12. AspNetCore 使用NLog日志,NLog是基于.NET平台开的类库!(又一神器)
  13. 20130401学习笔记
  14. 上传本地代码到github
  15. linux的rar,linux下rar的使用
  16. 在 Centos 安装 MySQL
  17. 【万里征程——Windows App开发】如何使用粘贴板
  18. SC-02-04-外包软件开发SOW工作说明书
  19. 在MAC上如何隐藏文件夹以及查看隐藏文件
  20. 高端域名出售如何选择交易平台?

热门文章

  1. rocket mq 监听端口_如何使用Jmeter实现MQ数据的发送和接收?性能测试实战篇
  2. 软件是怎样控制硬件的?
  3. 实现c++BMP图像的读取合成拆解加边框
  4. 个人所得税如何填写最划算?
  5. 孩子学习缺乏主动性,应该怎么做?
  6. 是不是人老了,子女都不愿和老人相处?
  7. 投资一个五星级酒店需要多钱?多长时间能回本?
  8. 应届生找工作是首先选择一个公司,还是选择一个行业?
  9. Wi-Fi模块与蓝牙模块有何区别?
  10. sql server序列_SQL Server中的Microsoft时间序列