zoj 3611 Ice Valley 状压BFS

来源:互联网 发布:miss的淘宝店网址 编辑:程序博客网 时间:2024/06/06 00:38

   500*500的平面,每格都有一个标记,表及含义如下:

标记:0 空白位置,在此处可以向上下左右四个方向走,保证0位置不超过100个。

标记:# 陷阱,走到此处会挂掉

标记:W 墙,这个位置不能走

标记:$ 盒子,在此处可以花费2秒打开盒子,取走钱,之后可以向上下左右四个方向走,保证$位置不超过10个。

标记:U,D,L,R 分别对应上下左右,在这个标记处,下一步只能按照标记的方向走。


由于0和$最多只有110个,所以可以把这些可以自由行动的点抽出来,重新建成一个图,也就是对原矩阵预处理一下。首先给这些点标下号,$在前(方便装压记录取钱情况)0在后,然后遍历矩阵,遍历到一个$或0时,枚举四个方向,看最近可以到达哪个$或0,同时记录话费,建成一个新图。预处理后就从起点开始BFS了,Dp[x][sta]表示在x节点,取钱状态为sta时的最小时间,每次扩展出一个新节点v时,若时间ti>dp[v][sta]就更新Dp的值,并且若v,sta这对状态没有在队列中就让它进队(类似SPFA)。最后便利一下dp[ed]的所有状态,找一个1最多的对应的时间输出就行了。

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <queue>using namespace std;typedef long long ll;const int fx[4]={0,1,0,-1};const int fy[4]={1,0,-1,0};struct EG{    int v,next,w;}edge[42000];int en;int g[220];const int inf=9999999;char s[550][550];int num[550][550];int n,m,p,q,x,y,z,k;int numa,numb;bool vis[550][550];bool check(int x,int y){    if (x>0 && x<=n && y>0 && y<=m && s[x][y]!='W' && s[x][y]!='#')    {        return true;    }    return false;}int trans(int x,int y,int &t){    memset(vis,false,sizeof vis);    while(s[x][y]!='0' && s[x][y]!='$')    {        t++;        if (s[x][y]=='L') y--;        else if (s[x][y]=='R') y++;        else if (s[x][y]=='U') x--;        else if (s[x][y]=='D') x++;        if (vis[x][y]) return -1;        if (!check(x,y)) return -1;        vis[x][y]=true;    }    return num[x][y];}int sx,sy,ex,ey;int dp[220][2048];bool inq[220][2048];struct node{    int id,sta;    node()    {    }    node(int x,int y)    {        id=x; sta=y;    }};int calc(int x){    int res=0;    while(x)    {        if (x&1) res++;        x>>=1;    }    return res;}void addedge(int u,int v,int w){    edge[en].v=v;    edge[en].w=w;    edge[en].next=g[u];    g[u]=en;    en++;}int main(){//    freopen("in.txt","r",stdin);    while(~scanf("%d%d",&n,&m))    {        memset(num,-1,sizeof num);        numa=numb=0;        for (int i=1; i<=n; i++)         scanf("%s",&s[i][1]);        scanf("%d%d%d%d",&sx,&sy,&ex,&ey);        for (int i=1; i<=n; i++)         for (int j=1; j<=m; j++)         {             if (s[i][j]=='$') num[i][j]=numb++;         }        numa=numb;        for (int i=1; i<=n; i++)         for (int j=1; j<=m; j++)         if (s[i][j]=='0') num[i][j]=numa++;         memset(g,-1,sizeof g);         en=0;         int tx,ty,ti;         int u,v;         for (int i=1; i<=n; i++)         for (int j=1; j<=m; j++)          if (num[i][j]!=-1)          {              u=num[i][j];              for (int k=0; k<4; k++)              {                  tx=i+fx[k];                  ty=j+fy[k];                  ti=1;                  if (check(tx,ty))                  {                     v=trans(tx,ty,ti);                     if (v!=-1)                     {                        addedge(u,v,ti);                     }                  }              }          }          int st=num[sx][sy];          int ed=num[ex][ey];          queue<node> q;          while(!q.empty())          {              q.pop();          }          memset(dp,0x3f,sizeof dp);          q.push(node(st,0));          dp[st][0]=0;          inq[st][0]=true;          while(!q.empty())          {              int u=q.front().id;              int v;              int sta=q.front().sta;              q.pop();              inq[u][sta]=false;              int tu,ts,ti;              for (int j=g[u]; j!=-1; j=edge[j].next)              {                  tu=u;                  ts=sta;                  ti=dp[u][sta];                  v=edge[j].v;                  ti+=edge[j].w;                  if (v<numb)                  {                         if (((1<<v)&ts)==0)                         {                             ti+=2;                             ts|=(1<<v);                         }                   }                    if (dp[v][ts]>ti)                     {                         dp[v][ts]=ti;                         if (!inq[v][ts])                         {                             q.push(node(v,ts));                             inq[v][ts]=true;                         }                     }              }          }          int ans=inf,tt=-1;          for (int i=0; i<(1<<numb); i++)          {              int tmp=calc(i);              if (tmp>tt && dp[ed][i]<inf)              {                  ans=dp[ed][i];                  tt=tmp;              }          }          if (ans==inf) puts("-1");          else printf("%d\n",ans);    }    return 0;}


 

0 0
原创粉丝点击