题面传送门

注意到这题中宝藏 \(+\) 炸弹个数最多只有 \(8\) 个,故考虑状压,设 \(dp[x][y][S]\) 表示当前坐标为 \((x,y)\),有且仅有 \(S\) 当中的物品被包围在凸多边形内部所走过的最少步数。

考虑转移,枚举与 \((x,y)\) 相邻的点 \((x',y')\)。但是 \(S\) 的变化可能有些棘手。这里有一个结论,对于某一点 \((x,y)\),任意引出一条射线,如果它与多边形有奇数个交点,那么 \((x,y)\) 就在多边形内部。由于这里引出的射线可以沿任何方向,那么我们不妨统一假设射线的方向都是向右,故这里的状态 \(S\) 就可以理解为:满足 \((x,y)\) 向右引出的射线与多边形交点个数为奇数的点的集合。

这样一来状态是倒搞明白了,但是直接这样转移还是可能会出现一些问题,因为有可能我们是从某个点 \((x,y)\) 向右走到 \((x,y+1)\),而对于某个横坐标也为 \(x\) 的点 \((x,y')\),它向右引出的射线与多边形出现了重合的情况,进而就不好计算交点个数。不过这个问题很容易解决,因为行走的路径不会经过宝藏/炸弹,故横向的线段并不会影响交点个数,于是只需计算纵向的线段就行了。

但是这样还是会出现问题。比方说下图,对于点 \(A\) 向右引出的橙色射线,如果按照我们的判断其与多边形有两个交点 \(B,C\),但如果我们把横向的线段去掉,将两个纵向线段拼在一起,就会发现有用的交点只有 \(1\) 个。这个问题也异常容易解决,考虑将每条纵向的线段看作一个上开下闭的线段,当从 \((x,y)\) 走到 \((x+1,y)\) 时只改变满足 \(x'=x+1,y'<y\) 的点 \((x',y')\) 的状态;当从 \((x,y)\) 走到 \((x-1,y)\) 时只改变满足 \(x'=x,y'<y\) 的点 \((x',y')\) 的状态。这样一来就可以避免这个问题了。

最短路转移即可。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc((x%10)+'0');}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=20;
const int MAXP=256;
const int MAXM=8;
const int INF=0x3f3f3f3f;
const int dx[]={1,0,-1,0};
const int dy[]={0,1,0,-1};
int n,m,sx,sy;char s[MAXN+3][MAXN+3];
int dp[MAXN+2][MAXN+2][MAXP+3];
int px[MAXM+2],py[MAXM+2],a[MAXM+2],c1=0,c2=0;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(s[i][j]=='S') sx=i,sy=j;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(isdigit(s[i][j])){
px[s[i][j]^48]=i;py[s[i][j]^48]=j;c1++;
} c2=c1;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(s[i][j]=='B') px[++c2]=i,py[c2]=j;
for(int i=1;i<=c1;i++) scanf("%d",&a[i]);
memset(dp,63,sizeof(dp));dp[sx][sy][0]=0;
queue<pair<pii,int> > q;q.push(mp(mp(sx,sy),0));
while(!q.empty()){
pair<pii,int> p=q.front();q.pop();
int x=p.fi.fi,y=p.fi.se,msk=p.se;
// printf("%d %d %d %d\n",x,y,msk,dp[x][y][msk]);
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
if(nx<1||nx>n||ny<1||ny>m) continue;
if(s[nx][ny]!='.'&&s[nx][ny]!='S') continue;
int nmsk=msk;
for(int j=1;j<=c2;j++) if((!(px[j]^x)&&!(i^2)||!(px[j]^nx)&&!i)&&py[j]<ny)
nmsk^=1<<j-1;
if(dp[nx][ny][nmsk]==INF){
dp[nx][ny][nmsk]=dp[x][y][msk]+1;
q.push(mp(mp(nx,ny),nmsk));
}
}
}
int ans=-INF;
for(int i=0;i<(1<<c1);i++) if(dp[sx][sy][i]!=INF){
int sum=0;
for(int j=0;j<c1;j++) sum+=a[j+1]*(i>>j&1);
chkmax(ans,sum-dp[sx][sy][i]);
} printf("%d\n",ans);
return 0;
}

Codeforces 375C - Circling Round Treasures(状压 dp+最短路转移)的更多相关文章

  1. Codeforces 375C Circling Round Treasures - 最短路 - 射线法 - 位运算

    You have a map as a rectangle table. Each cell of the table is either an obstacle, or a treasure wit ...

  2. 旅游(CSUST省赛选拔赛2+状压dp+最短路)

    题目链接:http://csustacm.com:4803/problem/1016 题目: 思路:状压dp+最短路,比赛的时候有想到状压dp,但是最短路部分写挫了,然后就卡死了,对不起出题人~dis ...

  3. CF 375C Circling Round Treasures [DP(spfa) 状压 射线法]

    C - Circling Round Treasures 题意: 在一个$n*m$的地图上,有一些障碍,还有a个宝箱和b个炸弹.你从(sx,sy)出发,走四连通的格子.你需要走一条闭合的路径,可以自交 ...

  4. Codeforces 453B Little Pony and Harmony Chest:状压dp【记录转移路径】

    题目链接:http://codeforces.com/problemset/problem/453/B 题意: 给你一个长度为n的数列a,让你构造一个长度为n的数列b. 在保证b中任意两数gcd都为1 ...

  5. codeforces 8C. Looking for Order 状压dp

    题目链接 给n个物品的坐标, 和一个包裹的位置, 包裹不能移动. 每次最多可以拿两个物品, 然后将它们放到包里, 求将所有物品放到包里所需走的最小路程. 直接状压dp就好了. #include < ...

  6. Codeforces 429C Guess the Tree(状压DP+贪心)

    吐槽:这道题真心坑...做了一整天,我太蒻了... 题意 构造一棵 $ n $ 个节点的树,要求满足以下条件: 每个非叶子节点至少包含2个儿子: 以节点 $ i $ 为根的子树中必须包含 $ c_i ...

  7. Codeforces 895C Square Subsets(状压DP 或 异或线性基)

    题目链接  Square Subsets 这是白书原题啊 先考虑状压DP的做法 $2$到$70$总共$19$个质数,所以考虑状态压缩. 因为数据范围是$70$,那么我们统计出$2$到$70$的每个数的 ...

  8. 【题解】codeforces 8c Looking for Order 状压dp

    题目描述 Lena喜欢秩序井然的生活.一天,她要去上大学了.突然,她发现整个房间乱糟糟的--她的手提包里的物品都散落在了地上.她想把所有的物品都放回她的手提包.但是,这里有一点问题:她一次最多只能拿两 ...

  9. Codeforces 895C Square Subsets:状压dp【组合数结论】

    题目链接:http://codeforces.com/problemset/problem/895/C 题意: 给你n个数a[i].(n <= 10^5, 1 <= a[i] <= ...

随机推荐

  1. netty系列之:使用netty实现支持http2的服务器

    目录 简介 基本流程 CleartextHttp2ServerUpgradeHandler Http2ConnectionHandler 总结 简介 上一篇文章中,我们提到了如何在netty中配置TL ...

  2. Sequence Model-week2编程题1-词向量的操作【余弦相似度 词类比 除偏词向量】

    1. 词向量上的操作(Operations on word vectors) 因为词嵌入的训练是非常耗资源的,所以ML从业者通常 都是 选择加载训练好 的 词嵌入(Embedding)数据集.(不用自 ...

  3. Beta阶段第三次会议

    Beta阶段第三次会议 完成工作 姓名 工作 难度 完成度 ltx 1.掌握小程序代码和相关知识2.构思小程序游客模式 轻 90% xyq 1.修改场地表格信息2.对原页面活动申请场地部分进行修改 轻 ...

  4. springboot读取配置文件中的信息

    在一个项目中,我们有时候会把一些配置信息写入到一个配置文件中,在java代码中读取配置文件的信息.在此记录下读取属性文件中的内容. 在springboot项目中,springboot的配置文件可以使用 ...

  5. C++的指针使用心得

    使用C++有一段时间了,C++的手动内存管理缺失很麻烦,一不小心容易产生内存泄漏.自己总结了一点使用原则(不一定对),备注一下,避免忘记. 1.类外部传来的指针不处理 2.Qt对象管理的内存不处理 3 ...

  6. 详解DNS域名解析系统(域名、域名服务器[根、顶级、授权/权限、本地]、域名解析过程[递归与迭代])

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105583806 学习课程:<2019王道考研计算机网络> 学习目的 ...

  7. 计算机网络之网络层路由选择协议(自治系统AS、RIP、OSPF、BGP)

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105313629 学习课程:<2019王道考研计算机网络> 学习目的 ...

  8. 计算机网络之流量控制(停止-等待协议、滑动窗口、后退N帧协议GBN、选择重传协议SR)、滑动窗口、可靠传输机制

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/104908762 学习课程:<2019王道考研计算机网络> 学习目的 ...

  9. python mysqlclient安装失败 Command "python setup.py egg_info" failed with error code 1

    python2 python3 中代码 pip install mysqlclient 都安装失败的话, 很有可能是你的操作系统中没有安装mysql 如果确定已经安装了,请忽略下面的内容. Ubunt ...

  10. poj 2311 Cutting Game (SG)

    题意: 有一张W*H的纸片. 每人每次可以横着撕或者竖着撕,先撕出1*1那一方胜. 数据范围: W and H (2 <= W, H <= 200) 思路: 很好抽象出游戏图的模型,用SG ...