HDOJ--3681--Prison Break(BFS預處理+狀態壓縮DP)
阿新 • • 發佈:2018-03-25
-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)