题目大意

给定一个 N∗M N*M的棋盘,棋盘上有障碍,陷阱和宝藏,每个宝藏都有一个权值。现在要求从起始位置用折线围出一个合法的多边形,其内部不能含有陷阱,并且不能经过障碍,而得到的收益为其围住的宝藏权值之和减去多边形的周长。现在要求输出最大的收益。(“B”为陷阱,”#”为障碍,数字为宝藏,“.”为空地,”S”为起始位置)

宝藏加陷阱的数量 ≤8 \leq 8
N,M≤20 N,M\leq 20

注:题目已经给出判断一个点是否在一个·多边形内的方法,为给需要判断的点向一个任意方向折出一条射线,如果有偶数个交点则这个点在多边形外部,否则就在内部(如果射线交于多边形上的一个定点,我们可以规定一个方向,每次累计边数时只累计固定方向的边)

解题思路

由于需要维护的点就只有宝藏和陷阱,而这两种东西总共只有8个所以我们需要考虑的点也就是由8个,我们暂且称为关键点。

首先为了判断一个点是否在多变围成的多变形内,我们可以先固定一个方向,所以我们就可以预处理出经过一个格子会改变哪些关键点所处射线交点的奇偶性。由于只有8个关键点,所以我们可以用一个二进制存下来。

那么现在问题就变得简单了,我们可以用状态 Fx y k F_{x~y~k}表示到达坐标 (x,y) (x,y)时每个关键点射线与当前围出线段交点的奇偶性,由于我们已经预处理出每个格子会对每个关键点造成的影响,我们只需要维护每种状态的最小周长。转移时我们要求的是周长尽量小,而每次转移只会是周长加1,那么我们就可以用 BFS BFS暴力转移。最后再根据状态统计答案就可以了。

程序

//YxuanwKeith
#include <cstring>
#include <cstdio>
#include <algorithm>using namespace std;
typedef long long LL;const int MAXN = 25, MAXP = 1 << 8, Inf = 1e9 + 7;struct BfsType {int x, y, state;} D[MAXN * MAXN * MAXP];int fx[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
int N, M, X, Y, Num, Prec, Val[10], Ord[MAXN][MAXN], Add[MAXN][MAXN], Map[MAXN][MAXN][MAXP];
char S[MAXN][MAXN];
bool Flag[MAXN][MAXN][MAXP];void Prepare() {for (int i = 1; i <= N; i ++)for (int j = 1; j <= M; j ++)if (S[i][j] == 'B') Ord[i][j] = ++ Prec;for (int i = 1; i <= N; i ++)for (int j = 1; j <= M; j ++) {if (S[i][j] == 'S') X = i, Y = j;if (S[i][j] == 'S' || S[i][j] == '.')for (int k = i + 1; k <= N; k ++)   if (Ord[k][j]) Add[i][j] |= (1 << (Ord[k][j] - 1));}
}void Bfs() {memset(Map, 60, sizeof Map);int l = 1, r = 1;D[r].x = X, D[r].y = Y, D[r].state = 0;Flag[X][Y][0] = 1;Map[X][Y][0] = 0;for (; l <= r; l ++) {int x = D[l].x, y = D[l].y, state = D[l].state;for (int i = 0; i < 4; i ++) {int xx = x + fx[i][0], yy = y + fx[i][1];if (S[xx][yy] == 'S' || S[xx][yy] == '.') {int New = state;if (i == 1) New ^= Add[x][y];if (i == 3) New ^= Add[xx][yy];if (Map[x][y][state] + 1 >= Map[xx][yy][New]) continue;Map[xx][yy][New] = Map[x][y][state] + 1;if (Flag[xx][yy][New]) continue;Flag[xx][yy][New] = 1;D[++ r].x = xx, D[r].y = yy, D[r].state = New;}}Flag[x][y][state] = 0;}
}void GetAns() {LL Ans = 0;for (int i = 0; i < (1 << Prec); i ++) {LL S = 0;for (int j = 0; j < Prec; j ++) if (i & (1 << j)) S += Val[j + 1];Ans = max(Ans, S - Map[X][Y][i]);}printf("%lld", Ans);
}int main() {    scanf("%d%d", &N, &M);Prec = 0;for (int i = 1; i <= N; i ++) {scanf("%s", S[i] + 1);for (int j = 1; j <= M; j ++) if (S[i][j] >= '0' && S[i][j] <= '9') ++ Prec, Ord[i][j] = S[i][j] - '0';} for (int i = 1; i <= 8; i ++) Val[i] = -Inf;for (int i = 1; i <= Prec; i ++) scanf("%d", &Val[i]);Prepare();Bfs();GetAns();
}

GDOI2016模拟3.15 圈地游戏 暴力图论相关推荐

  1. python编写赛车游戏单机版_使用Python中OrderedDict模拟一个简单的竞速游戏排名

    上一篇,我们梳理了Python中关于字典排序的一些常用方法(杂乱无章的数据结构如何进行排序,简明讲述Python字典排序那些事).其中,我们讲到了Python的collections模块中的Order ...

  2. 2020.03.11模拟赛15(第一题)

    1.水果盛宴(fruit) 题目描述 贝茜又再一次地闯入了 Farmer John 的房子!她在厨房发现了一堆柠檬和一堆橘子(每堆都有无限多个),并且,她希望尽可能地多吃. 贝茜的有一个饱腹值上限 T ...

  3. 【GDOI2016模拟3.16】幂(容斥 + 模型复杂转化)

    [GDOI2016模拟3.16]幂 \(X\in[1,A],Y\in[1,B]\),问:\(x^y\)的不用取值个数. \(A,B\)都是\(10^9\)级别. 然后我们开搞. 首先,假设一个合法的\ ...

  4. MODE —— 两个人在计算机上玩圈叉游戏|井字游戏(知识点:二维数组)

    问题描述: 让两个人在计算机上玩井字游戏(也称圈叉游戏). 井字游戏就是一个3X3的方格,两个人轮流在方格中输入标记X 或者 O .谁先使自己的3个标记链接成水平,垂直或对角线.谁就是赢家. 运行结果 ...

  5. LYVC揭秘硅谷核心基金圈投资游戏规则

    本文讲的是LYVC揭秘硅谷核心基金圈投资游戏规则[IT168 资讯]从最早期的半导体企业,到Intel.苹果等巨头首次展露锋芒,再到2000年的互联网泡沫破灭,随着经济与科技形势不断起伏,硅谷风险投资 ...

  6. 15款Cocos2d-x游戏源码

    (1)用cocos2d-x开发的中国象棋游戏源码 使用Cocos2d-X2.2.3开发的一款中国象棋游戏,游戏中可以实现.新局面.悔棋.游戏音乐.胜利后会显示游戏结果. 源码下载:http://www ...

  7. [双指针|模拟] leetcode 15 三数之和

    [双指针|模拟] leetcode 15 三数之和 1.题目 题目链接 给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ? ...

  8. 15款Cocos2d-x游戏源码 1

    转自:http://blog.okbase.net/iphone/archive/4619.html (1)用cocos2d-x开发的中国象棋游戏源码 使用Cocos2d-X2.2.3开发的一款中国象 ...

  9. python——模拟抓狐狸的小游戏

    模拟抓狐狸的小游戏 假设一共有一排5个洞口,小狐狸最开始的时候在其中一个洞口,然后人随机打开一个洞口,如果里面有小狐狸就抓到了.如果洞口里没有小狐狸就明天再来抓,但是第二天小狐狸会在有人来抓之前跳到隔 ...

最新文章

  1. AI学术大地震---YOLO之父退出CV界,以此来反对AI算法用于军事和隐私窥探
  2. android 画布旋转,Android-在安卓开发中,如何实现一个简单的图片旋转
  3. python爬虫,记录一下爬取过程,列表数据,翻页,post方式,保存字典
  4. 【HTML5CSS3进阶学习02】Header的实现·CSS中的布局
  5. VC6下使用WebLink控件
  6. [github高级控件] 带你走近 - CircleIndicator指示器原点动画切换
  7. 数据库课设——简单的图书管理系统
  8. 如何用计算机函数来求加权总分,Excel小技巧-使用函数「SUMPRODUCT」计算加权后的总和及平均值...
  9. 中兴新支点服务器安装,U盘安装中兴新支点操作系统(NewStart)的方法
  10. js中求2个数的最大值的几种方法
  11. 闲人闲谈ERP项目逸事——德国做SAP项目回忆
  12. Eclipse设置运行内存大小
  13. 2017年全国研究生电子设计大赛上海赛区感触
  14. 新家入住气味难忍 除去甲醛有妙招
  15. 百度、阿里、小米决战智能音箱
  16. 520礼物清单、送男友实用礼物排行榜
  17. Flutter中基于Dio实现Token Refresh
  18. 读书笔记《世界金融史》
  19. 服务器缺少字体文件导致下载文件乱码解决方案
  20. 模型部署到移动端_分分钟打开倾斜摄影模型,新版本的老子云移动端也太好用了吧!...

热门文章

  1. 外接 USB 摄像头(UVC Camera)
  2. 人工智能 | 四个关于普通人的故事
  3. 浅谈NATS消息中间件
  4. 五十音三天快速记忆方法汇总
  5. 数据中心基础设施是应该纵向扩展还是横向扩展?
  6. alios是安卓吗_详解YUNOS系统和安卓系统到底有什么区别
  7. opencv reshape 深拷贝 浅拷贝之坑
  8. .NetCore3.1接入Consul的服务端和客户端代码整理
  9. Seo站内优化通常需要做的细节有哪些?
  10. Codeforces Round #646 (Div. 2)E. Tree Shuffling 题解(dfs)