[胡泽聪 趣题选讲]大包子环绕宝藏-[状压dp]
Description
你有一个长方形的地图,每一个格子要么是一个障碍物,要么是一个有一定价值的宝藏,要么是一个炸弹,或者是一块空地。你的初始位置已经给出。
你每次可以走到上、下、左、右这四个相邻的格子。你不允许走出这幅地图,不允许进入有宝藏、障碍物或是炸弹的地方。你需要规划一个闭合的路线(起点和终点都必须在初始位置)来取得宝藏。注意这个路线围成的多边形中不可以包含炸弹。假设路线围成的多边形包含的所有宝藏的价值之和为v,并且你从起点到终点走了 k步(从一个格子走到旁边的格子算作一步),那么你沿该路线走一次将可以获得v-k的利润。
你的任务是规划一个不包含炸弹的闭合路线,并可获得最大的利润。
注意路线可以自交。为了确定一个格子是否在这条路线里面,请使用以下算法判断:
1.假设该点的坐标为需要判断的点为 p(i,j) ,该点不在路线上
2.从该点往任意方向作一条射线,如果与路线相交奇数次,我们就认为这个格子在这条路线里面,否则这个格子在这条路线外面。
n,m<=20。炸弹和宝藏的个数总和不超过8个,保证只有1个初始点。
Solution
本题难点其实就是判断格子是否在路线里面。(题目好良心系列)我选定的射线方向是竖直向上(当然其他方向也ok呀)。
所以,如果画出路径,所有的射线只会和横向路径相交(竖向的路径就直接忽略啦)
对于每一小段横向路径(即点(x,y)到(x,y+1)),我们记录这一小段路径的右端点。如此以保证奇偶性正确。
5 — 4 —3
| |
6 9 2
| |
7 — 8 — 1
如图,我们沿1-8寻找回路,则被记录的点有3,4,8,1。
虽然5和7没有被记录到,但这不影响9(多边形内部)和多边形外部的点的判断。
(当然,如果是记录所有横向路径的点也可以,例如记3,4,5,7,8,1;不过这就需要加些特判了)
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N=,K=;
int f[][]={{,},{,-},{,},{-,}};
int tx[],ty[],cnt,k;
int n,m,sx,sy,w[];
char mp[][];
int dp[][][<<K];
int q[**(<<K)],l,r;
int num(int x,int y,int z){return x*N*(<<K)+y*(<<K)+z;}
int getx(int c){return c/(N*(<<K));}
int gety(int c){return c/(<<K)%N;}
int getz(int c){return c%(<<K);}
int main()
{
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
{
scanf("%s",mp[i]+);
for (int j=;j<=m;j++) if (mp[i][j]=='S'){mp[i][j]='.';sx=i;sy=j;}
else if (mp[i][j]>''&&mp[i][j]<'')
{tx[mp[i][j]-'']=i;ty[mp[i][j]-'']=j;cnt++;mp[i][j]='#';}
} k=cnt;
for (int i=;i<=n;i++) for (int j=;j<=m;j++)
if (mp[i][j]=='B')
{mp[i][j]='#';tx[cnt]=i;ty[cnt]=j;cnt++;}
for (int i=;i<k;i++) scanf("%d",&w[i]); memset(dp,0x3f,sizeof(dp));
dp[sx][sy][]=;
q[]=num(sx,sy,);
l=r=;
int _x,_y,_z,zz;
while (l<=r)
{
_x=getx(q[l]);_y=gety(q[l]);_z=getz(q[l]);l++;
for (int i=;i<;i++)
{
if (_x+f[i][]<=n&&_x+f[i][]&&_y+f[i][]&&_y+f[i][]<=m&&mp[_x+f[i][]][_y+f[i][]]=='.')
{
zz=_z;
if (!i) for (int j=;j<cnt;j++) if (tx[j]>_x&&ty[j]==_y) zz^=<<j;
if (i==)
for (int j=;j<cnt;j++) if (tx[j]>_x+f[i][]&&ty[j]==_y+f[i][]) zz^=<<j;
if (dp[_x][_y][_z]+<dp[_x+f[i][]][_y+f[i][]][zz])
{
dp[_x+f[i][]][_y+f[i][]][zz]=dp[_x][_y][_z]+;
q[++r]=num(_x+f[i][],_y+f[i][],zz);
}
}
}
}
bool _is;int ans=,sum,t;
for (int i=;i<<<cnt;i++)
{
sum=;_is=;
for (int j=;j<cnt;j++)
{
t=i&(<<j);
if (j>=k&&t) _is=;
if (j<k&&t) sum+=w[j];
}
if (_is) ans=max(ans,sum-dp[sx][sy][i]);
}
cout<<ans;
}
[胡泽聪 趣题选讲]大包子环绕宝藏-[状压dp]的更多相关文章
- 【bzoj2734】集合选数(有点思维的状压dp)
题目传送门:bzoj2734 这题一个月前看的时候没什么头绪.现在一看,其实超简单. 我们对于每个在$ [1,n] $范围内的,没有因数2和3的数$ d $,将它的倍数$ 2^a 3^b d $一起处 ...
- PJ考试可能会用到的数学思维题选讲-自学教程-自学笔记
PJ考试可能会用到的数学思维题选讲 by Pleiades_Antares 是学弟学妹的讲义--然后一部分题目是我弄的一部分来源于洛谷用户@ 普及组的一些数学思维题,所以可能有点菜咯别怪我 OI中的数 ...
- 正睿OI DAY3 杂题选讲
正睿OI DAY3 杂题选讲 CodeChef MSTONES n个点,可以构造7条直线使得每个点都在直线上,找到一条直线使得上面的点最多 随机化算法,check到答案的概率为\(1/49\) \(n ...
- 2019暑期金华集训 Day6 杂题选讲
自闭集训 Day6 杂题选讲 CF round 469 E 发现一个数不可能取两次,因为1,1不如1,2. 发现不可能选一个数的正负,因为1,-1不如1,-2. hihoCoder挑战赛29 D 设\ ...
- BZOJ 2734 洛谷 3226 [HNOI2012]集合选数【状压DP】【思维题】
[题解] 思维题,看了别人的博客才会写. 写出这样的矩阵: 1,3,9,... 2,6,18,... 4,12.36,... 8,24,72,... 我们要做的就是从矩阵中选出一些数字,但是不能选相邻 ...
- 【bzoj3195】【 [Jxoi2012]奇怪的道路】另类压缩的状压dp好题
(上不了p站我要死了) 啊啊,其实想清楚了还是挺简单的. Description 小宇从历史书上了解到一个古老的文明.这个文明在各个方面高度发达,交通方面也不例外.考古学家已经知道,这个文明在全盛时期 ...
- 【bzoj1087】【互不侵犯King】状压dp裸题(浅尝ACM-D)
[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=54329606 向大(hei)佬(e)势力学(di ...
- QDUOJ 来自xjy的签到题(bfs+状压dp)
来自xjy的签到题 Description 爱丽丝冒险来到了红皇后一个n*n大小的花园,每个格子由'.'或'#'表示,'.'表示爱丽丝可以到达这个格子,‘#’表示爱丽丝不能到达这个格子,爱丽丝每1 ...
- 刷题总结——bzoj1725(状压dp)
题目: 题目描述 Farmer John 新买了一块长方形的牧场,这块牧场被划分成 N 行 M 列(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地. FJ ...
随机推荐
- APP性能测试指标和测试方法
流量 常用方法 方法一:Android系统自带统计功能(总体流量数值) Proc/uid_stat/{UID}/tcp_snd和tcp_rcv UID是每个app安装时候分配的唯一编号用于识别该app ...
- Django接收URL问号参数
问题概览: 一开始需求是想通过URL接收参数,但是一直固守通过正则表达式的方式接收参数,即形如(?P<parm>.+)的方式. 后面发现(/?)在http://regex101.com是可 ...
- Software Development Engineer, RDS Database Engines, Seattle
DESCRIPTION About UsAmazon Aurora is an exciting new area of innovation for AWS, and the PostgreSQL- ...
- 49_分析代理类的作用与原理及AOP概念
生活中的代理 武汉人从武汉的代理商手中买联想电脑和直接跑到北京传智播客旁边来找联想总部买电脑,你觉得最终的主体业务目标有什么区别吗?基本上一样吧,都解决了核心问题,但是,一点区别都没有吗?从代理商那里 ...
- vc获取当前进程CPU使用率
double GetCPUUserRate() { HANDLE hProcess=::GetCurrentProcess(); static DWORD s_dwTickCountOld = 0; ...
- SDN2017 第二次作业
阅读文章<软件定义网络(SDN)研究进展>,并根据所阅读的文章,书写一篇博客,回答以下问题(至少3个): 1.为什么需要SDN?SDN特点? 2.SDN的基本思想? 3.ONF全称是什么, ...
- Django商城项目笔记No.11用户部分-QQ登录1获取QQ登录网址
Django商城项目笔记No.11用户部分-QQ登录 QQ登录,亦即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目. 若想实现QQ登录,需要成为QQ互联 ...
- PyQt5--QCheckBox
1 # -*- coding:utf-8 -*- ''' Created on Sep 20, 2018 @author: SaShuangYiBing Comment: ''' import sys ...
- html简单介绍(一)
什么是html HTML 是用来描述网页的一种语言.HTML 指的是超文本标记语言 (Hyper Text Markup Language)HTML 不是一种编程语言,而是一种标记语言 (markup ...
- 6、JVM--类文件结构(下)
6.4 字节码指令简介 Java虚拟机的指令由一个字节长度的.代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成.由 ...