题意:
要求在一张网格图上走出一条闭合路径,不得将炸弹包围进去,使围出的总价值减去路径长度最大。
分析:
大致同poj3182,再加上状态压缩。w[x]表示该状态下的sum{val},dp[x][y][k]表示围圈,在k状态下的最短dis。|状态:选择了1-8中哪几个
转移的时候 xor一下就好
ps:bomb怎么搞?直接把他的val=-oo,扔到bfs中。正确性自行脑补
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int N=25; const int M=1<<10; const int dx[4]={0,0,1,-1}; const int dy[4]={1,-1,0,0}; int dp[N][N][M],w[M],val[N];char mp[N][N]; int n,m,cnt,ans,sx,sy,gx[N],gy[N],px,py,pk,nx,ny,nk; struct node{ int x,y,k; node(int x=0,int y=0,int k=0):x(x),y(y),k(k){} }; bool ok(int j){ if(nx==gx[j]&&ny<gy[j]){ if(px<nx) return 1; } if(px==gx[j]&&py<gy[j]){ if(px>nx) return 1; } return 0; } void bfs(){ memset(dp,-1,sizeof dp); queue<node>q; q.push(node(sx,sy,0)); dp[sx][sy][0]=0; while(!q.empty()){ node t=q.front();q.pop(); px=t.x;py=t.y;pk=t.k; if(px==sx&&py==sy) ans=max(ans,w[pk]-dp[px][py][pk]); for(int i=0;i<4;i++){ nx=px+dx[i];ny=py+dy[i];nk=pk; if(nx<1||ny<1||nx>n||ny>m||(mp[nx][ny]!='.'&&mp[nx][ny]!='S')) continue; for(int j=0;j<cnt;j++) if(ok(j)) nk^=1<<j; if(dp[nx][ny][nk]==-1){ dp[nx][ny][nk]=dp[px][py][pk]+1; q.push(node(nx,ny,nk)); } } } printf("%d ",ans); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%s",mp[i]+1); for(int i=1,p;i<=n;i++){ for(int j=1;j<=m;j++){ if(mp[i][j]=='S') sx=i,sy=j; if(mp[i][j]>'0'&&mp[i][j]<'9'){ p=mp[i][j]-'1';cnt++; gx[p]=i;gy[p]=j; } } } for(int i=0;i<cnt;i++) scanf("%d",&val[i]); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(mp[i][j]=='B'){ gx[cnt]=i;gy[cnt]=j;val[cnt]=-100000; cnt++; } } } w[0]=0; for(int S=1;S<(1<<cnt);S++){ for(int i=0;i<cnt;i++){ if(S&(1<<i)) w[S]+=val[i]; } } bfs(); return 0; }