1. 程式人生 > >HDOJ--3681--Prison Break(BFS預處理+狀態壓縮DP)

HDOJ--3681--Prison Break(BFS預處理+狀態壓縮DP)

-s cin pos hdoj con 多少 電源 too 最大的

題意

F--起點

S--空格

G--能量池,只能充一次電,充完之後G變為S,也可已選擇不充而當成普通的S

D--激光區,不能走

Y--電源開關

M被關在一所監獄之中,F為起點,每走一步(上下左右)消耗1節能量,只要關閉完所有的Y就可以直接飛出去,可以到能量池裏進行充電。問M要想出去所攜帶的電池的最小尺寸是多少。註意:能量池和開關的總和小於15。

思路

首先將圖中所有的F,G,Y找出來,並用BFS求出這三種標誌任意兩者的距離。具體看例子

GDDSS
SSSFS
SYGYS
SGSYS
SSYSS
//經處理後變為
F--0:  1,3
Y--1:  2,1
Y--2:  2,3
Y--3:  3,3
Y--4:  4,2
G--5:  0,0
G--6:  2,2
G--7:  3,1//之所以要先F再Y再G是為了狀壓的時候只要考慮前5個點(0~4)都走過(即都變成1)時方便處理。

//經BFS後記錄任意亮點的距離(無視充電池,但要考慮激光區)
0,0--0
0,1--3
0,2--1
0,3--2
0,4--4
0,5--4
0,6--2
0,7--4
1,0--3
1,1--0
1,2--2
1,3--3
1,4--3
1,5--3
1,6--1
1,7--1
2,0--1
2,1--2
2,2--0
2,3--1
2,4--3
2,5--5
2,6--1
2,7--3
3,0--2
3,1--3
3,2--1
3,3--0
3,4--2
3,5--6
3,6--2
3,7--2
4,0--4
4,1--3
4,2--3
4,3--2
4,4--0
4,5--6
4,6--2
4,7--2
5,0--4
5,1--3
5,2--5
5,3--6
5,4--6
5,5--0
5,6--4
5,7--4
6,0--2
6,1--1
6,2--1
6,3--2
6,4--2
6,5--4
6,6--0
6,7--2
7,0--4
7,1--1
7,2--3
7,3--2
7,4--2
7,5--4
7,6--2
7,7--0

狀態轉移方程要設一個輔助的dp用來存當前走了都少步,遇到能量池時步數變為0;dp_v用來存走到當前狀態歷史最大的步數 。//不好理解

dp[i+sta[j]][j]=dp[i][k]+g[k][j]; 或 dp[i+sta[j]][j]=0;

dp_v[i+sta[j][j]=max(dp[i+sta[j]][j],dp_v[i][k]);

AC代碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
int sta[20]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};
int dp[32768][20];
int dp_v[32768][20];
int flag[32768][20];
int g[20][20];
char Map[20][20],c;
int N,M,ctor,nY;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
const int INF=0x7fffffff;

struct node
{
     int x,y;
};
node a[20],temp;
struct tool
{
    int num,step;
};
tool t[20][20];

//預處理
void import();
void init();
void BFS();


int main()
{
    while(scanf("%d%d",&N,&M)&&N&&M)
    {
        init();
        import();
        BFS();
        int ans=INF;
        int ans1=INF;
        int jud=sta[nY]-1;
        int jx=sta[ctor]-1;
        queue<node>q;
        while(!q.empty()) q.pop();
        temp.x=1;
        temp.y=0;
        dp[temp.x][temp.y]=0;
        dp_v[temp.x][temp.y]=0;
        flag[temp.x][temp.y]=0;
        q.push(temp);
        while(!q.empty())
        {
            int i=q.front().x;
            int k=q.front().y;
            q.pop();
            flag[i][k]=1;
            for(int j=0;j<ctor;++j)
            {

                if((sta[j]&i)==0&&g[k][j]!=-1)
                {
                    temp.x=i+sta[j];
                    temp.y=j;
                    if(j<nY&&(dp_v[temp.x][temp.y]==-1||dp_v[temp.x][temp.y]>max(dp[i][k]+g[k][j],dp_v[i][k])))
                    {
                         dp[temp.x][temp.y]=dp[i][k]+g[k][j];
                         dp_v[temp.x][temp.y]=max(dp[temp.x][temp.y],dp_v[i][k]);
                         if((temp.x&jud)==jud)
                         {
                              ans=min(ans,dp_v[temp.x][temp.y]);

                         }
                         else if(temp.x<jx&&flag[temp.x][temp.y])
                         {
                             q.push(temp);
                             flag[temp.x][temp.y]=0;
                         }
                    }
                    if(j>=nY&&(dp_v[temp.x][temp.y]==-1||dp_v[temp.x][temp.y]>max(dp[i][k]+g[k][j],dp_v[i][k])))
                    {

                         dp[temp.x][temp.y]=0;
                         dp_v[temp.x][temp.y]=max(dp[i][k]+g[k][j],dp_v[i][k]);
                        if(temp.x<jx&&flag[temp.x][temp.y])
                         {
                             q.push(temp);
                             flag[temp.x][temp.y]=0;
                         }
                    }
                }
            }
        }
        if(N==1&&M==1)
            printf("0\n");
        else if(ans==INF)
            printf("-1\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

void init()
{
    memset(g,-1,sizeof(g));
    memset(flag,-1,sizeof(flag));
    memset(dp,-1,sizeof(dp));
    memset(dp_v,-1,sizeof(dp));
    for(int i=0;i<N;++i)
    {
        for(int j=0;j<M;++j)
        {
            t[i][j].num=-1;
            t[i][j].step=-1;
        }
    }
}
void BFS()
{
    for(int i=0;i<ctor;++i)
    {
        for(int I=0;I<N;++I) for(int J=0;J<M;++J)   t[I][J].step=-1;

        queue<node>q;
        temp.x=a[i].x;
        temp.y=a[i].y;
        t[temp.x][temp.y].step=0;
        q.push(temp);
        while(!q.empty())
        {
            int x=q.front().x;
            int y=q.front().y;
            q.pop();
            for(int j=0;j<4;++j)
            {
                temp.x=x+dx[j];
                temp.y=y+dy[j];
                if(temp.x>=0&&temp.x<N&&temp.y>=0&&temp.y<M&&Map[temp.x][temp.y]!=‘D‘&&(t[temp.x][temp.y].step==-1||t[temp.x][temp.y].step>t[x][y].step+1))
                {
                    t[temp.x][temp.y].step=t[x][y].step+1;
                    q.push(temp);
                }
            }
        }
        for(int I=0;I<N;++I)
        {
            for(int J=0;J<M;++J)
            {
                int j=t[I][J].num;
                if(j!=-1)
                {
                    g[i][j]=t[I][J].step;
                }
            }
        }
    }
}

void import()
{
    for(int i=0;i<N;++i)
        {
            for(int j=0;j<M;++j)
            {
                cin>>c;
                Map[i][j]=c;
            }
        }
        ctor=0;
        for(int i=0;i<N;++i)
        {
            for(int j=0;j<M;++j)
            {
                if(Map[i][j]==‘F‘)
                {
                    a[ctor].x=i;
                    a[ctor].y=j;
                    t[i][j].num=ctor;
                    ++ctor;
                }
            }
        }
        for(int i=0;i<N;++i)
        {
            for(int j=0;j<M;++j)
            {
                if(Map[i][j]==‘Y‘)
                {
                    a[ctor].x=i;
                    a[ctor].y=j;
                    t[i][j].num=ctor;
                    ++ctor;
                }
            }
        }
        nY=ctor;
        for(int i=0;i<N;++i)
        {
            for(int j=0;j<M;++j)
            {
                if(Map[i][j]==‘G‘)
                {
                    a[ctor].x=i;
                    a[ctor].y=j;
                    t[i][j].num=ctor;
                    ++ctor;
                }
            }
        }
}

  

---恢復內容結束---

HDOJ--3681--Prison Break(BFS預處理+狀態壓縮DP)