zoukankan      html  css  js  c++  java
  • Bzoj1556 墓地秘密

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 128  Solved: 56
    [Submit][Status][Discuss]

    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

    动规 状压DP

    BFS预处理出石头某方向到另一石头某方向的距离,之后就是普通的状压DP

    代码一如既往地慢……status里差点垫底2333

    ↑估计是BFS写得不好,太像SPFA了

    ↑f数组可以把终点石头和方向合并进一维里,说不定快一点?

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cstdlib>
      7 #include<cmath>
      8 #include<vector>
      9 using namespace std;
     10 const int mxn=200010;
     11 const int mx[5]={1,-1,0,0};//下 上 左 右 
     12 const int my[5]={0,0,-1,1};
     13 int read(){
     14     int x=0,f=1;char ch=getchar();
     15     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     16     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     17     return x*f;
     18 }
     19 char s[120];
     20 bool mp[110][110];
     21 int f[1<<16][16][4];
     22 int dis[16][4][16][4];
     23 int ax[16],ay[16],T;
     24 int id[120][120];
     25 int d[110][110];
     26 int n,m;
     27 int hd,tl,qx[mxn],qy[mxn],qt[mxn];
     28 inline bool check(int x,int y){
     29     if(x<0 || x>=n || y<0 || y>=m)return 0;
     30     return 1;
     31 }
     32 bool inq[110][110];
     33 void BFS(int s,int di){
     34     memset(d,0x3f,sizeof d);
     35     hd=1;tl=0;
     36     int i=di;
     37     int nx=ax[s]+mx[i];int ny=ay[s]+my[i];
     38     if(!s)nx=ax[s],ny=ay[s];
     39     if(!check(nx,ny) || mp[nx][ny])return;
     40     qx[++tl]=nx;qy[tl]=ny;
     41     qt[tl]=0;
     42     d[nx][ny]=0;//当前所在位置,已经停下次数 
     43     //
     44     while(hd<=tl){
     45         int x=qx[hd],y=qy[hd],t=qt[hd];inq[x][y]=0;
     46         for(int dir=0;dir<4;dir++){
     47             int nx=x,ny=y;
     48             while(check(nx,ny)){
     49                 if(mp[nx][ny]){
     50                     int tar=id[nx][ny];if(tar==-1)break;
     51                     dis[s][di][tar][dir^1]=min(dis[s][di][tar][dir^1],qt[hd]+1);
     52                     break;
     53                 }
     54                 if(d[nx][ny]>qt[hd]+1){
     55                     d[nx][ny]=qt[hd]+1;
     56                     if(!inq[nx][ny]){
     57                         qx[++tl]=nx;qy[tl]=ny;qt[tl]=d[nx][ny];
     58                         inq[nx][ny]=1;
     59                     }
     60                 }
     61                 nx+=mx[dir],ny+=my[dir];
     62             }
     63         }
     64         ++hd;
     65     }
     66 }
     67 void solve(){
     68     int ed=(1<<(T+1))-1;
     69     memset(f,0x3f,sizeof f);
     70     f[1][0][0]=f[1][0][1]=f[1][0][2]=f[1][0][3]=0;
     71     for(int i=1;i<=ed;i++){
     72         for(int j=0;j<=T;j++){//起点 
     73             if(!(i&(1<<j)))continue;
     74             for(int k=0;k<=T;k++){//终点 
     75                 if(i&(1<<k))continue;
     76                 for(int dj=0;dj<4;dj++){//起点方向 
     77                     for(int dk=0;dk<4;dk++){//终点方向 
     78                         if(dis[j][dj][k][dk]>1e7)continue;
     79                         f[i|(1<<k)][k][dk]=min(f[i|(1<<k)][k][dk],f[i][j][dj]+dis[j][dj][k][dk]);
     80                     }
     81                 }
     82             }
     83         }
     84     }
     85     int ans=1e9;
     86     for(int i=0;i<=T;i++)
     87         for(int j=0;j<4;j++){
     88             ans=min(ans,f[ed][i][j]);
     89         }
     90     printf("%d
    ",ans);
     91     return;
     92 }
     93 int main(){
     94 //    freopen("in.in","r",stdin);
     95     int i,j;
     96     n=read();m=read();T=read();
     97     for(i=0;i<n;i++){
     98         scanf("%s",s);
     99         for(j=0;j<m;j++)if(s[j]=='#')mp[i][j]=1;
    100     }
    101     memset(id,-1,sizeof id);
    102     for(i=1;i<=T;i++){
    103         ax[i]=read()-1;ay[i]=read()-1;
    104         id[ax[i]][ay[i]]=i;
    105     }
    106     for(i=0;i<=0;i++){ax[i]=read()-1;ay[i]=read()-1;id[ax[i]][ay[i]]=i;}//初始位置 
    107     memset(dis,0x3f,sizeof dis);
    108     for(i=0;i<=T;i++){
    109         if(!i)BFS(i,0);
    110         else for(j=0;j<4;j++){
    111             BFS(i,j);
    112         }
    113     }
    114     solve();
    115     return 0;
    116 }
  • 相关阅读:
    C++类中的函数重载
    C++中的友元
    bzoj 2820
    莫比乌斯函数
    bzoj 2440: [中山市选2011]完全平方数
    莫比乌斯反演1
    [转]C++ 指针和引用
    P2756 飞行员配对方案问题
    P2055 [ZJOI2009]假期的宿舍
    P2654 原核生物培养
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6437992.html
Copyright © 2011-2022 走看看