【BZOJ1556】墓地秘密 DP
来源:互联网 发布:手机淘宝4.2.2安卓版 编辑:程序博客网 时间:2024/04/27 17:19
Description
费尽周折,终于将众将士的残骸运送到了KD军事基地地底层的大型墓地入口。KD的伙伴和战友们都参加了这次重大的送葬仪式。右边是一扇敞开的大门,进去便是墓地了,左边是一堵凹进去的墙,没有什么特别的地方。 部队缓缓进入右边的门,一切。。。就这么结束了么。。。。。 此时, F却没有跟上队伍,在一般MM都会有的强烈的第六感之下,她来到了左边这堵墙前一探究竟。扫去了重重的灰尘之后,墙上一块凹进去的手掌印清晰可见了。F试着用自己的手对上去,竟刚好合适。稍微用力一按,顿时一声巨响,地上马上裂开一大洞,F和那厚重的墙瞬间一起落入深渊!当其他人听见了巨大的声响而赶来的时候,一切都恢复平静了。只有那堵墙后面的世界,震惊了所有生物。这到底是什么,为什么会在墓地里面? 墙的后面是一个巨大的迷宫!简单的一行字浮现在了一侧的墙上:猛烈撞击所有发亮的机关石。当大伙好奇的蜂拥进迷宫的时候,一块莫名其妙的巨石竟从入口上方落下,将入口完全堵死了!石头上清晰的写了一行字:超过规定时间不能完成任务,全部人都会困死于此。看来,只有硬着头皮去闯,才有可能离开这里,并且探索出这个迷宫的秘密了。 于是大家马上散开,很快摸清了这里的地形,剩下的任务就是轰击石头了。那么。。。论攻击力最高的,自然非功夫DP莫属,而且功夫DP可以使用前滚翻移动法,能够瞬间获得巨大的初速度,并且在直线运动的时候速度将近似光速,质量无穷大,那动能自然就。。。。。。DP每次可以选择朝一个方向滚动,并且可以自己选择在某位置停下来,或者撞击到墙和石头的时候被迫停下来。由于直线速度过快,所以要停下来拐弯自然就是很麻烦的事情。那么只有制定出一个最好的运动方法,使得DP停下来次数最少,才能争取尽量多的时间!
Input
第一行3个正整数N、M和T。表示这是一个N*M的迷宫,并且有T个机关石。 接下来用一个N*M的字符矩阵描述迷宫,.表示是空地,#表示是墙。 接下来T行每行2个正整数X、Y,描述一个机关石的位置,它在迷宫对应的位置是#。不会有两个机关石在同一位置。 最后一行2个正整数X0、Y0,表示DP的初始位置。
Output
一个正整数ANS,表示DP至少要停下来多少次才能撞击完所有的机关石。
Sample Input
4 6 3
……
….#.
…..#
….#.
2 5
3 6
4 5
1 5
Sample Output
5
HINT
数据规模:
对于10%的数据,N、M<=10,T<=2;
对于40%的数据,N、M<=50,T<=10;
对于100%的数据,N、M<=100,T<=15;
注意事项:
迷宫的最外层是墙,即任何时候不可能滚出迷宫,墙是撞不烂的(好硬)!
每次DP只能选择4个基本方向中的一个方向移动,每块机关石都必须被撞击,撞击后变成普通的墙。
Source
HNOI2009集训Day8
原题传送门
看到总的机关个数不多,不难想到可以使用状压:f(s,r,c,dir)表示当且已经触碰到的开关的集合为s,DP位于r行c列,朝向为dir的停下来的次数。当然,细细分析,状态中只有机关周围的四个格子是有用的,状态可简化为f(s,t,dir),表示DP位于第t个机关的dir方向。转移只需要枚举上一次从哪个点过来即可。这需要预处理出任意两个位于机关四周的点之间的距离。
好的……这个题的难点我认为反而在这个bfs上面……bfs的队列中需要保证前面的状态的停留次数不多于后面的,就可以保证一定可以搜到最优解了……要做到这一点有许多的细节。在一个状态加入队列的时候,我们需要把在这个方向上,在网格图中位于前方的状态进行更新(但是不用加入队列)就可以了。
#include<cstdio>#include<iostream>#include<cstring>#define clr(a,b) memset(a,b,sizeof(a))#define maxn 100#define bit(a) (1<<(a))#define inf (1<<28)#define id(a,b) ((a)*4+(b))using namespace std;const int mr[]={1,-1,0,0},mc[]={0,0,1,-1};int n,m,t,map[maxn+10][maxn+10],rp[maxn+10],cp[maxn+10];inline int min(int a,int b){return a<b?a:b;}struct data{ int r,c,dir; data(){} data(int r,int c,int dir):r(r),c(c),dir(dir){}};data que[maxn*maxn*4+10];int vis[maxn+10][maxn+10][4],d[maxn+10][maxn+10][4],he,ta;int can(int r,int c){return r>0&&r<=n&&c>0&&c<=m&&map[r][c]==-1;}void push(data u){ que[++ta]=u; data v=u; int ud=d[u.r][u.c][u.dir]; for(int i=1;i<=inf;i++){ v.r+=mr[v.dir]; v.c+=mc[v.dir]; if(can(v.r,v.c)&&!vis[v.r][v.c][v.dir])d[v.r][v.c][v.dir]=ud; }else break; }}void bfs(int rs,int cs){ clr(d,16); clr(vis,0); if(!can(rs,cs))return; he=0,ta=-1; for(int i=0;i<4;i++){ d[rs][cs][i]=0; vis[rs][cs][i]=1; push(data(rs,cs,i)); } while(he<=ta){ data u=que[he++],v=data(u.r,u.c,0); int ud=d[u.r][u.c][u.dir]; for(int i=1;i<=inf;i++){ v.r+=mr[u.dir]; v.c+=mc[u.dir]; if(can(v.r,v.c)){ for(int j=2;j<=3;j++){ v.dir=u.dir^j; if(!vis[v.r][v.c][v.dir]){ vis[v.r][v.c][v.dir]=1; d[v.r][v.c][v.dir]=ud+1; push(v); } } }else break; } }}int f[1<<16][70],dis[70][70];int main(){ scanf("%d%d%d",&n,&m,&t); if(n<=10&&m<=10&&t==2)srand(time(NULL)); char e[120]; for(int i=1;i<=n;i++){ scanf("%s",e+1); for(int j=1;j<=m;j++)if(e[j]=='.')map[i][j]=-1; else map[i][j]=-2; } for(int i=0;i<t;i++)scanf("%d%d",&rp[i],&cp[i]); clr(dis,16); for(int u=0;u<t;u++) for(int i=0;i<4;i++)if(can(rp[u]+mr[i],cp[u]+mc[i])){ bfs(rp[u]+mr[i],cp[u]+mc[i]); for(int v=0;v<t;v++)if(v!=u) for(int j=0;j<4;j++)if(can(rp[v]+mr[j],cp[v]+mc[j]))dis[id(u,i)][id(v,j)]=d[rp[v]+mr[j]][cp[v]+mc[j]][j^1]; } int r0,c0; scanf("%d%d",&r0,&c0); bfs(r0,c0); clr(f,16); for(int i=0;i<t;i++) for(int j=0;j<4;j++)if(can(rp[i]+mr[j],cp[i]+mc[j]))f[bit(i)][id(i,j)]=d[rp[i]+mr[j]][cp[i]+mc[j]][j^1]; int ans=inf; for(int s=1;s<bit(t);s++){ for(int v=0;v<4*t;v++)if(bit(v/4)&s){ for(int u=0;u<4*t;u++)if(bit(u/4)&s&&(u/4!=v/4)) f[s][v]=min(f[s][v],f[s^bit(v/4)][u]+dis[u][v]+1); if(s==bit(t)-1)ans=min(ans,f[s][v]); } } printf("%d\n",ans+1); return 0;}
- 【BZOJ1556】墓地秘密 DP
- bzoj1556 (DP)
- BZOJ 1556: 墓地秘密【状压DP
- BZOJ 1556 墓地秘密
- 李莲英死因之谜及墓地里的惊天秘密
- 【DP】秘密文件
- 快乐墓地
- 墓地雕像
- POJ 1187 陨石的秘密 ()[]{}帯权dp
- poj 1187 陨石的秘密(字符串DP)
- POJ 1187-陨石的秘密(DP)
- Graveyard(墓地雕塑)
- LA3708 - Graveyard(墓地)
- 墓地的女孩
- LA3708 Graveyard 墓地雕塑
- UVA-墓地雕塑
- graveyard,neerc(墓地雕塑)
- LA3708墓地雕塑
- Poj1325 Machine Schedule
- 学习C# 继承 封装 多态
- 03环信好友管理 - 好友请求同意后刷新联系人列表
- hdu 5500 Reorder the Books【贪心】【思维】
- 数据结构循环队列
- 【BZOJ1556】墓地秘密 DP
- 给UITableView添加UITapGestureRecognizer 每个Item多事件点击出现崩溃
- 通讯录的联系人操作(CRUD)
- UVa--514 Rails (stack)
- 《Linux常用命令第一关(1)》
- 【报表神器】——ECharts
- Android----MVP模式的理解
- 算法导论例程——红黑树
- C++对象数组与对象指针