[胡泽聪 趣题选讲]大包子环绕宝藏-[状压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 ...
随机推荐
- 从零自学Java-4.使用字符串来交流
1.使用字符串来存储文本: 2.在程序中显示字符串: 3.在字符串中包含特殊的字符: 4.拼接字符串: 5.在字符串中包含变量: 6.比较字符串: 7.判断字符串的长度: 程序Credits:显示一部 ...
- centos6.5安装mysql
1.yum -install mysql mysql-server -y 2.修改mysql的root的密码 登录:mysql -uroot 修改密码: use ...
- window平台搭建Hudson服务器
1.1 环境 Microsoft Windows server 2008 x64 1.2 资源下载 TortoiseSVN-1.7.11.23600-x64-svn-1.7.8.msi h ...
- 无法将数据库从SINGLE_USER模式切换回MULTI_USER模式(Error 5064),及查找SQL Server数据库中用户spid(非SQL Server系统spid)的方法
今天公司SQL Server数据库无意间变为SINGLE_USER模式了,而且使用如下语句切换回MULTI_USER失败: ALTER DATABASE [MyDB] SET MULTI_USER W ...
- NewEmployeesLearnNotes——新人程序员学习计划V1.1
百度云链接:https://pan.baidu.com/s/1BzoT79tV1QGwIQTjkGA4CQ 密码:k78i 修改中...
- IP地址的分类——a,b,c 类是如何划分的【转】
ip分类已经是耳熟能详了.但是说的都比较繁琐,这里简述一下,便于以后复习. IP地址,一共分成了5类,范围分别如下: A类IP:从0.0.0.0 – 127.255.255.255,共有1677721 ...
- Huawei DHCP 全局配置与接口配置
网络拓扑图如下所示: 说明: 1.交换机Ge0/0/1口和Ge0/0/2口配置基于全局的DHCP: 2.交换机Ge0/0/3口配置基于端口的DHCP: 3.交换机上配置vlan 10 .vlan 20 ...
- 恶意代码分析_01_YARA规则_CLAMAV病毒库
写在前面的话: 上一篇文章里,我们已经初步了解了Malware的一些知识,并且利用Clamscan创建了自己的md5类型的病毒库, 那在这篇文章中,我将带领大家一起,来进一步了解病毒库的相关知识,以及 ...
- MySQL基础之---mysqlimport工具和LOAD DATA命令导入文本文件
1.mysqlimport工具的使用 看一下命令的使用方法: shell > mysqlimport -u root -p [--LOCAL] DBname File [option] --f ...
- PHP生成excel表格文件并下载
本文引自网络,仅供自己学习之用. 利用php导出excel我们大多会直接生成.xls文件,这种方便快捷. function createtable($list,$filename){ header(& ...