题面传送门

注意到这题中宝藏 \(+\) 炸弹个数最多只有 \(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. 禅道开源版 Ldap认证插件开发

    禅道开源版-Ldap插件开发 背景 由于开源版无法使用ldap认证,所以在此分享一下自己开发禅道的ldap开发过程,希望对你有所帮助. 简单说一下这个插件的功能: 1.跳过原有禅道认证,使用ldap认 ...

  2. 分库分表利器之Sharding Sphere(深度好文,看过的人都说好)

    Sharding-Sphere Sharding-JDBC 最早是当当网内部使用的一款分库分表框架,到2017年的时候才开始对外开源,这几年在大量社区贡献者的不断迭代下,功能也逐渐完善,现已更名为 S ...

  3. 【UE4 设计模式】单例模式 Singleton Pattern

    概述 描述 保证一个类只有一个实例 提供一个访问该实例的全局节点,可以视为一个全局变量 仅在首次请求单例对象时对其进行初始化. 套路 将默认构造函数设为私有, 防止其他对象使用单例类的 new运算符. ...

  4. vue3.x移动端适配px2rem

    1.什么是px2rem px2rem是一个插件能将px自动转换为rem,以适配各种不同的屏幕尺寸.前端开发可以直接使用设计稿量出的尺寸或者蓝湖给出的px进行布局,这样极大的提高了开发效率. 2.前提条 ...

  5. 6. 站在巨人的肩膀学习Java Filter型内存马

    本文站在巨人的肩膀学习Java Filter型内存马,文章里面的链接以及图片引用于下面文章,参考文章: <Tomcat 内存马学习(一):Filter型> <tomcat无文件内存w ...

  6. SpringBoot加密配置属性

    一.背景 在系统中的运行过程中,存在很多的配置属性,比如: 数据库配置.阿里云配置 等等,这些配置有些属性是比较敏感的,是不应直接以明文的方式出现在配置文件中,因此对于这些配置我们就需要加密来处理. ...

  7. 常用JAVA API :String 、StringBuilder、StringBuffer的常用方法和区别

    摘要 本文将介绍String.StringBuilder类的常用方法. 在java中String类不可变的,创建一个String对象后不能更改它的值.所以如果需要对原字符串进行一些改动操作,就需要用S ...

  8. GeoServer-Manager应用:java编码实现发布矢量数据或栅格数据至GeoServer

    目录 简介与下载 依赖 编码发布矢量数据 编码发布栅格数据 简介与下载 GeoServer-Manager是使用Java编写的面向GeoServer的客户端库,通过GeoServer的REST管理接口 ...

  9. cf16E Fish(状压DP)

    题意: N只FISH.每个回合会有一只FISH吃掉另一个FISH.直到池塘里只剩一只FISH. 给出aij:第i只FISH吃掉第J只FISH的概率. 问每一只FISH是最后存活者的概率. Input ...

  10. hdu 5178 pairs(BC第一题,,方法不止一种,,我用lower_bound那种。。。)

    题意: X坐标上有n个数.JOHN想知道有多少对数满足:x[a]-x[b]<=k(题意给)[a<b] 思路: 额,,,直接看代码吧,,,, 代码: int T,n,k; int x[100 ...