[胡泽聪 趣题选讲]大包子环绕宝藏-[状压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 ...
随机推荐
- iOS 开发多线程 —— GCD(1)
本文是根据文顶顶老师的博客学习总结而来,如有不妥之处,还望指出.http://www.cnblogs.com/wendingding/p/3807716.html 概览: /* 纯c语言,提供了非常多 ...
- Android友盟增量更新
1.增量升级的原理 增量更新的原理就是将本地apk与服务器端最新版本比对,并得到差异包.比如现在的版本是1.1.4,大小是7.2M,新版本是1.1.5.大小是7.3M.我们发现两个版本只有0.1M的差 ...
- 5,注释、分支结构、循环结构、伪“选择结构”
注释: python使用#作为行注释符,使用三引号作为多行注释符 分支结构: if-else: a=int(input("你的成绩是:")) if a>60: print(& ...
- IBM ServerGuide引导盘全系列下载网址
IBM ServerGuide引导盘全系列下载网址 官网链接 https://www.ibm.com/support/home/docdisplay?lndocid=SERV-GUIDE v9.30 ...
- python基础学习19----socket网络编程
网络通信三要素 ip地址:InetAddress 网络中设备的标识,不易记忆,可用主机名(计算机的标识号) 端口号:用于标识进程的逻辑地址,不同进程的标识(正在运行的软件的标识号) 传输协议:通讯的规 ...
- angular、jquery、vue 的区别与联系
angular和jquery的区别 angular中是尽量避免操作DOM, angular是基于数据驱动, 适合做数据操作比较繁琐的项目,angular适用于单页面开发,是一个比较完善的mvvm框架, ...
- Shell学习---Shell脚本的静态检查工具shellcheck
Shell脚本的静态检查工具shellcheck ubuntu下 apt install shellcheck ,即可安装shellcheck.写完shell脚本,记得用它检查一下,能给你点建议的.要 ...
- [工具]iperf测试带宽
之前被要求测试网卡带宽能力,发现了iperf这个工具,记录下来防止遗忘. iperf是个开源跨平台测试带宽工具,windows.linux.macOS--都支持,安装也挺方便. 1.安装 地址:htt ...
- Javascript之DOM性能优化
原文地址:http://ce.sysu.edu.cn/hope/Item/140355.aspx 作者:陈古松 来源:本站原创 发布时间:2015-03-14 更新时间:2015-03-14 点击数 ...
- 死磕nginx系列--nginx入门
nginx 功能介绍 Nginx因为它的稳定性.丰富的模块库.灵活的配置和低系统资源的消耗而闻名.业界一致认为它是Apache2.2+mod_proxy_balancer的轻量级代替者,不仅是因为响应 ...