BZOJ1556 墓地秘密
题意
费尽周折,终于将众将士的残骸运送到了KD军事基地地底层的大型墓地入口。KD的伙伴和战友们都参加了这次重大的送葬仪式。右边是一扇敞开的大门,进去便是墓地了,左边是一堵凹进去的墙,没有什么特别的地方。 部队缓缓进入右边的门,一切。。。就这么结束了么。。。。。 此时, F却没有跟上队伍,在一般MM都会有的强烈的第六感之下,她来到了左边这堵墙前一探究竟。扫去了重重的灰尘之后,墙上一块凹进去的手掌印清晰可见了。F试着用自己的手对上去,竟刚好合适。稍微用力一按,顿时一声巨响,地上马上裂开一大洞,F和那厚重的墙瞬间一起落入深渊!当其他人听见了巨大的声响而赶来的时候,一切都恢复平静了。只有那堵墙后面的世界,震惊了所有生物。这到底是什么,为什么会在墓地里面? 墙的后面是一个巨大的迷宫!简单的一行字浮现在了一侧的墙上:猛烈撞击所有发亮的机关石。当大伙好奇的蜂拥进迷宫的时候,一块莫名其妙的巨石竟从入口上方落下,将入口完全堵死了!石头上清晰的写了一行字:超过规定时间不能完成任务,全部人都会困死于此。看来,只有硬着头皮去闯,才有可能离开这里,并且探索出这个迷宫的秘密了。 于是大家马上散开,很快摸清了这里的地形,剩下的任务就是轰击石头了。那么。。。论攻击力最高的,自然非功夫DP莫属,而且功夫DP可以使用前滚翻移动法,能够瞬间获得巨大的初速度,并且在直线运动的时候速度将近似光速,质量无穷大,那动能自然就。。。。。。DP每次可以选择朝一个方向滚动,并且可以自己选择在某位置停下来,或者撞击到墙和石头的时候被迫停下来。由于直线速度过快,所以要停下来拐弯自然就是很麻烦的事情。那么只有制定出一个最好的运动方法,使得DP停下来次数最少,才能争取尽量多的时间!
输入:第一行3个正整数N、M和T。表示这是一个N*M的迷宫,并且有T个机关石。 接下来用一个N*M的字符矩阵描述迷宫,`.`表示是空地,`#`表示是墙。 接下来T行每行2个正整数X、Y,描述一个机关石的位置,它在迷宫对应的位置是`#`。不会有两个机关石在同一位置。 最后一行2个正整数X0、Y0,表示DP的初始位置。
输出:一个正整数ANS,表示DP至少要停下来多少次才能撞击完所有的机关石。
\(N,M \leq 100 , T \leq 15\)
分析
参照hzwer的题解。
对于40%的数据
状压墙的撞击情况,然后广搜
d[x][y][st][dir]表示到x行y列,撞击情况为st,朝向为dir的最小转向数
对于100%的数据
只有机关四周的四个格子是有意义的
只会在这些格子间之间走最短路(可以广搜来求),那么只剩下4T个格子,预处理每个格子到另一个格子撞机关的最少转向次数
最后状压dp即可,用\(f(s,t)\)表示已撞击状态为s,然后出发点情况为t的最小话费。直接对每个状态枚举转移态即可。
复杂度\(O(4T \cdot 4NM + 2^T \cdot 4T \cdot 4T)\)
由于我预处理写的是spfa,会多花些时间
这题主要难点在于预处理出距离。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<ctime>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
rg T data=0;
rg int w=1;
rg char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
{
data=data*10+ch-'0';
ch=getchar();
}
return data*w;
}
template<class T>T read(T&x)
{
return x=read<T>();
}
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
co int INF=0x3f3f3f3f;
co int MAXN=100,MAXT=15;
int n,m,t;
char buf[MAXN];
int rock[MAXN][MAXN];
int x[MAXT],y[MAXT];
co int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int p(int x,int d)
{
return 4*x+d;
}
int dis[4*MAXT+1][4*MAXT+1];
int d[MAXN][MAXN][4];
bool inq[MAXN][MAXN];
queue <pii> Q;
bool inrg(int x,int y)
{
return 0<=x&&x<n&&0<=y&&y<m;
}
void bfs(int bx,int by,int id)
{
if(!inrg(bx,by)||rock[bx][by])
return;
memset(d,0x3f,sizeof d);
for(int i=0;i<4;++i)
d[bx][by][i]=0;
Q.push(pii(bx,by));
inq[bx][by]=1;
while(Q.size())
{
int x=Q.front().first,y=Q.front().second;
Q.pop();
inq[x][y]=0;
for(int i=0;i<4;++i)
{
int nx=x+dx[i],ny=y+dy[i];
if(!inrg(nx,ny)||rock[nx][ny])
continue;
for(int j=0;j<4;++j)
if(d[x][y][i]+(i!=j)<d[nx][ny][j])
{
d[nx][ny][j]=d[x][y][i]+(i!=j);
if(!inq[nx][ny])
{
Q.push(pii(nx,ny));
inq[nx][ny]=1;
}
}
}
}
for(int i=0;i<t;++i)
for(int j=0;j<4;++j)
{
int s=INF,nx=x[i]+dx[j],ny=y[i]+dy[j];
for(int k=0;k<4;++k)
s=min(s,d[nx][ny][k]+(nx+dx[k]!=x[i]||ny+dy[k]!=y[i]));
dis[id][p(i,j)]=s;
}
}
int f[1<<MAXT][4*MAXT+1];
void dp()
{
for(int i=0;i<(1<<t);++i)
for(int x=0;x<=4*t;++x)
f[i][x]=INF;
f[0][4*t]=0;
for(int i=0;i<(1<<t);++i)
for(int x=0;x<=4*t;++x)
if(f[i][x]<INF)
for(int y=0;y<4*t;++y)
{
int s=i|(1<<(y/4));
f[s][y]=min(f[s][y],f[i][x]+dis[x][y]+1); // 加上到机关石停止的开销
}
int ans=INF;
for(int x=0;x<=4*t;++x)
{
// cerr<<"f "<<(1<<t)-1<<" "<<x<<" = "<<f[(1<<t)-1][x]<<endl;
ans=min(ans,f[(1<<t)-1][x]);
}
printf("%d\n",ans);
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
memset(dis,0x3f,sizeof(dis));
read(n);read(m);read(t);
for(int i=0;i<n;++i)
{
scanf("%s",buf);
for(int j=0;j<m;++j)
if(buf[j]=='#')
rock[i][j]=1;
}
for(int i=0;i<t;++i)
x[i]=read<int>()-1,y[i]=read<int>()-1; // edit 1: -1
for(int i=0;i<t;++i)
for(int j=0;j<4;++j)
bfs(x[i]+dx[j],y[i]+dy[j],p(i,j));
int bx=read<int>()-1,by=read<int>()-1; // edit 1
bfs(bx,by,4*t);
// for(int i=0;i<=4*t;++i)
// for(int j=0;j<=4*t;++j)
// cerr<<dis[i][j]<<(j==4*t?'\n':' ');
dp();
return 0;
}
BZOJ1556 墓地秘密的更多相关文章
- BZOJ 1556 墓地秘密
2333333333333333333333333333333333333333333333 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 辣鸡出题人辣鸡出题人辣鸡出题人辣鸡出题人辣鸡 ...
- bzoj 1556: 墓地秘密【状压dp+spfa】
显然是状压,显然不可能把所有格子压起来 仔细观察发现只有机关周围的四个格子有用以及起点,所以我们用spfa处理出这些格子两两之间的距离(注意细节--这里写挂了好几次),然后设f[s][i]为碰完的机关 ...
- bzoj 1556 墓地秘密 —— 状压DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1556 预处理出两个障碍四个方向之间的距离(转弯次数),就可以状压DP了: 但预处理很麻烦.. ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- BZOJ 刷题总结(持续更新)
本篇博客按照题号排序(带*为推荐题目) 1008 [HNOI2008]越狱 很经典的题了..龟速乘,龟速幂裸题,, 1010 [HNOI2008]玩具装箱toy* 斜率优化 基本算是裸题. 1012 ...
- TypeScript: Angular 2 的秘密武器(译)
本文整理自Dan Wahlin在ng-conf上的talk.原视频地址: https://www.youtube.com/watch?v=e3djIqAGqZo 开场白 开场白主要分为三部分: 感谢了 ...
- [C#] string 与 String,大 S 与小 S 之间没有什么不可言说的秘密
string 与 String,大 S 与小 S 之间没有什么不可言说的秘密 目录 小写 string 与大写 String 声明与初始化 string string 的不可变性 正则 string ...
- 网站的SEO以及它和站长工具的之间秘密
博客迁移没有注意 URL 地址的变化,导致百度和 google 这两只爬虫引擎短时间内找不到路.近段时间研究了下国内最大搜索引擎百度和国际最大搜索引擎google的站长工具,说下感受. 百度的站长工具 ...
- 《WePayUI组件设计的秘密》——2016年第一届前端体验大会分享
本文是博主参加第一届前端体验大会 | 物勒工名做的分享<WePayUI组件设计的秘密>,内容主要分为2个部分: 一.浅析UI库/框架的未来 讨论的UI库或者框架,主要包含展示和交互的css ...
随机推荐
- unity调用Android百度地图
由于个人是Android小白,在这个配置上面被折磨了很久,因此写下这篇文章 工具:eclipse + unity5.6.1 首先去百度地图开发者平台下载你需要的资源,我只需要显示地图和定位,这个时候你 ...
- day20 project+查看新闻列表 + 点赞 + 图片验证码 + 评论和多级评论 + 后台管理 + webSocket + kindEditor
Day20回顾: 1. 请求生命周期 2. 中间件 md = [ "file_path.classname" ] process_request[可有可无] process_res ...
- CF 187C Weak Memory 优先队列 难度:2
http://codeforces.com/problemset/problem/187/C 这道题可以用二分+dfs检测,或者优先队列解 此处用了优先队列解法 从起点出发,维护一个优先队列,内容是p ...
- golang简易版聊天室
功能需求: 创建一个聊天室,实现群聊和单聊的功能,直接输入为群聊,@某人后输入为单聊 效果图: 群聊: 单聊: 服务端: package main import ( "fmt" ...
- 【zznu-夏季队内积分赛3-I】逛超市
题目描述 “别人总说我瓜,其实我一点也不瓜,大多数时候我都机智的一批“我宝儿姐背包学的太差了,你们谁能帮我解决这道题,我就让他做我的男朋友!宝儿姐现在在逛超市,超市里的种类实在是太多了,每种都有很多很 ...
- 团队项目:"Jarvis For Chat"
"Jarvis For Chat"项目简介 项目详情信息已经在上一篇博客中详细给出,详请查看博客 团队成员 姓名 学号 张扬(队长) 031602345 苏韫月 031602631 ...
- lcx端口转发 linux版
一.端口转发使用 1.攻击机上执行以下命令 ./lcx -p1 -p2 -m 在本地监听3389端口,并将发送到本机3389端口的数据传递到本机2222端口 2.跳板机上执行以下命令 ./lcx -h ...
- functools 和 itertools
functools 补充 1 wraps 在编写装饰器时,在实现前加入 @functools.wraps(func) 可以保证装饰器不会对被装饰函数造成影响.wraps 保存被装饰函数的原信息 def ...
- 微信红包算法TEST
1.基本算法 设定总金额为10元,有N个人随机领取:N=1 则红包金额=X元: N=2 为保证第二个红包可以正常发出,第一个红包金额=0.01至9.99之间的某个随机数 第二个红包=10-第一个红包金 ...
- (转)MapReduce Design Patterns(chapter 6 (part 1))(十一)
Chapter 6. Metapatterns 这种模式不是解决某个问题的,而是处理模式的关系的.可以理解为“模式的模式”.首先讨论的是job链,把几个模式联合起来解决复杂的,有多个阶段要处理的问题. ...