题目大意

给定一个$n\times m$的网格$(n,m\leq 20)$,每个格子都是$S\space \#\space B\space x\space .$中第一个。

$S$表示起点,保证有且仅有一个。

$\#$表示障碍,不能通过,$.$表示空地,可以通过

$B$表示炸弹,$x$是一个数字,每个数子代表着一个宝藏,每个宝藏有对应的价值(可以为负)。

炸弹和宝藏的数量不超过$8$个

现在你要规划一条从$S$出发,每次只能沿着上下左右四个方向,只能经过除了空地和起点的可以自交的闭合回路,使得这条回路缩圈起来的格子中不含有炸弹,将圈起来的格子中所有宝藏之和加起来记为$sum$,路径长度记为$len$,求$\max(sum-len)$。

举个例子

这遍是原图中的最优解。

题解

我们先想办法解决如何判断一个点是否在回路内。

考虑一个点$(i,j)$(第$i$行第$j$列),从它出发向左下作一条方向无限贴近于正下的射线,通过这条射线与回路相交次数的奇偶性来判断,即枚举所有$k(k>i)$,计算$sum$表示回路经过$(k,j),(k,j-1)$两个点之间的次数和。

若$sum$为奇数,那么在形内,否则在形外。

接下来就简单了,由于炸弹和宝藏的和不超过$8$个,我们直接将炸弹看做价值为$-INF$的宝藏,然后每个宝藏是否在形内进行装状态压缩。

这样就可以从起点出发进行$BFS$了,$F_{(i,j,k)}$表示从$S$出发,到达$(i,j)$,所有宝藏是否在形内的情况为$k$的最短步数。最后只需枚举状态进行计算取$\max$即可。

最终复杂度为$O(nmk2^k)$,我图着省事把其中一个$k$改成了$n$也能过。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define M 30
#define bas 1000
#define INF 10000000
using namespace std;
int read(){
int nm=0,fh=1; char cw=getchar();
for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
return nm*fh;
}
const int dx[]={0,0,-1,1},dy[]={-1,1,0,0};
int n,m,q[INF],dis[M][M][550],pos[M][M],T,B,tot,val[M];
int xt[M],yt[M],xb[M],yb[M],hd,tl,Sx,Sy,ans;
char ch[M];
void ins(int x,int y,int sta){q[tl++]=(x*bas+y)*bas+sta;}
void tk(int &x,int &y,int &sta){sta=q[hd]%bas,q[hd]/=bas,y=q[hd]%bas,q[hd]/=bas,x=q[hd],hd++;}
int main(){
n=read(),m=read(),memset(dis,0x3f,sizeof(dis));
for(int i=1;i<=n;i++){
scanf("%s",ch+1);
for(int j=1;j<=m;j++){
if(ch[j]=='.') continue;
if(ch[j]=='B') B++,xb[B]=i,yb[B]=j,pos[i][j]=++tot,val[tot]=-INF;
else if(ch[j]=='#') pos[i][j]=-1;
else if(ch[j]=='S') ins(i,j,0),Sx=i,Sy=j,dis[i][j][0]=0;
else ++T,xt[ch[j]-'0']=i,yt[ch[j]-'0']=j,pos[i][j]=++tot;
}
}
for(int i=1;i<=T;i++) val[pos[xt[i]][yt[i]]]=read();
while(hd<tl){
int x,y,now; tk(x,y,now);
for(int j=0;j<4;j++){
int xx=x+dx[j],yy=y+dy[j],rem=now;
if(pos[xx][yy]||xx<1||yy<1||xx>n||yy>m) continue;
if(y!=yy){
for(int j=1,nw=max(y,yy);j<xx;j++)
if(pos[j][nw]>0) rem^=(1<<(pos[j][nw]-1));
}
if(dis[xx][yy][rem]<INF) continue;
dis[xx][yy][rem]=dis[x][y][now]+1,ins(xx,yy,rem);
}
}
for(int i=1;i<(1<<tot);i++){
int res=0;
for(int dt=1;dt<=tot;dt++) if((i>>(dt-1))&1) res+=val[dt];
ans=max(ans,res-dis[Sx][Sy][i]);
} printf("%d\n",ans); return 0;
}

  

CF221C Circling Round Treasures的更多相关文章

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

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

  2. Circling Round Treasures CodeForces - 375C

    C. Circling Round Treasures time limit per test 1 second memory limit per test 256 megabytes input s ...

  3. 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 ...

  4. 【CF375C】Circling Round Treasures

    Portal --> CF375C Solution 一个有趣的事情:题目中有很大的篇幅在介绍如何判断一个位置在不在所围的多边形中 那么..给了方法当然就是要用啊 ​ 首先是不能包含\('B'\ ...

  5. Circling Round Treasures(codeforces 375c)

    题意:要求在一张网格图上走出一条闭合路径,不得将炸弹包围进去,使围出的总价值减去路径长度最大. /* 类似于poj3182的做法,只不过出现了多个点,那么就用状态压缩的方法记录一个集合即可. */ # ...

  6. Codeforces 375C - Circling Round Treasures(状压 dp+最短路转移)

    题面传送门 注意到这题中宝藏 \(+\) 炸弹个数最多只有 \(8\) 个,故考虑状压,设 \(dp[x][y][S]\) 表示当前坐标为 \((x,y)\),有且仅有 \(S\) 当中的物品被包围在 ...

  7. Codeforces 375

    A 7的所有的余数都可以用1,6,8,9排列得到,然后搞一下就可以了. B 可以用类似于单调队列的东西搞.具体看代码: /* * Problem: B. Maximum Submatrix 2 * A ...

  8. Treasures and Vikings(两次搜索)

    Treasures and Vikings https://www.luogu.org/problemnew/show/P4668 题意翻译 你有一张藏宝图,藏宝图可视为 N×MN×M 的网格.每个格 ...

  9. SQL Server 随机数,随机区间,随机抽取数据rand(),floor(),ceiling(),round(),newid()函数等

    在查询分析器中执行:select rand(),可以看到结果会是类似于这样的随机小数:0.36361513486289558,像这样的小数在实际应用中用得不多,一般要取随机数都会取随机整数.那就看下面 ...

随机推荐

  1. 使用3DES+Base64来加密传输iOS应用数据

    本文转载至 http://www.erblah.com/post/objective-c/shi-yong-3des-base64lai-jia-mi-chuan-shu-iosying-yong-s ...

  2. ASIHTTP

    本文转载至 http://www.th7.cn/Program/IOS/201303/128223.shtml     向服务器端上传数据 ASIFormDataRequest ,模拟 Form表单提 ...

  3. Sum of Remainders(数学题)

    F - Sum of Remainders Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I ...

  4. Netty实现java多线程Post请求解析(Map参数类型)—SKY

    netty解析Post的键值对 解析时必须加上一个方法,ch.pipeline().addLast(new HttpObjectAggregator(2048)); 放在自己的Handel前面. ht ...

  5. 优化tomcat启动速度

    1.去掉不需要的jar包,这样tomcat在启动时就可以少加载jar包里面的class文件. 2.跳过一些与TLD files.注解.网络碎片无关的jar包,通过在conf/catalina.prop ...

  6. 【python】-- GIL锁、线程锁(互斥锁)、递归锁(RLock)

    GIL锁 计算机有4核,代表着同一时间,可以干4个任务.如果单核cpu的话,我启动10个线程,我看上去也是并发的,因为是执行了上下文的切换,让看上去是并发的.但是单核永远肯定时串行的,它肯定是串行的, ...

  7. java中枚举类型的使用

    Java 枚举(enum) 详解7种常见的用法 JDK1.5引入了新的类型——枚举.在 Java 中它虽然算个“小”功能,却给我的开发带来了“大”方便. web项目里实体类使用枚举类型: 一般在该实体 ...

  8. 几则js表达式

    过滤大段文本里的标签.标签格式 <...>,如下匹配标签然后替换成空 校验邮箱是否符合: 去掉行首行尾空格: 检测字符串是否包含中文:(utf8编码)

  9. 从 零开始 无差错 装好nginx+PHP

    由于这两天 一直有人追问 nginx为何报错,为何php没装好啥的,大多原因是 : 1.编译与yum混合安装,导致很多包的路径不对,进而报错 2.yum源比较旧,导致 与新版本的php不匹配 3.安装 ...

  10. CentOS取消屏幕保护自动锁屏功能

    CentOS系统在用户闲置一段时间(默认为5分钟)后,会启动屏幕保护程序(默认的屏保为黑屏),并要求重新输入密码才能回到原来的桌面. 设置屏幕保护:System -> Preferences - ...