-
J - Jailbreak
- Gym - 100625J
- 题意:有两个犯人要逃出监狱,监狱中有很多门,打开一道门需要花费1的体力,
- 当一个犯人打开门后另一个就不需要在打开了。走到地图外就算逃出监狱了。
- ‘*’表示墙,‘.’表示路,‘#’表示门(花费1体力),问两个人都逃出去的最小花费,保证有解。
- 思路:最初想到最优解应该是两个人最终汇于一点然后一起走出去花费最小,但是想到有特例两个人分别走自己的走出去
- 为最优解也可能,比如两个人无法找到一个交点这一种情况就无法用找到公共交点来解决,但是只要把图的外面加一圈‘.’
- 所有的就都连起来了,因为题目已说每个犯人都能逃脱,所以外面加上一圈‘.’后都能连通并且没有增加话费。
- 所以这是所有情况都可以通过枚举两个人的交点来解决,因为最终他们都得出来。
- 所需要增加一个外面的点(我选择的0,0)枚举一下这三个点在哪里交叉花费最小即可。
-
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define maxn 155 bool vis[maxn][maxn]; char mmp[maxn][maxn]; int s[3][maxn][maxn]; int t,n,m,x[3],y[3],c,ans; struct node { int x,y,door; bool operator<(const node&b)const { return door>b.door; } } top,temp; int to[5][2]= {{0,1},{0,-1},{1,0},{-1,0}}; bool judge(int x,int y) { if(x<0||y<0||x>n+1||y>m+1||vis[x][y]||mmp[x][y]=='*') return false; return true; } void bfs(int ord,int x,int y) { memset(vis,0,sizeof(vis)); priority_queue<node>q; if(mmp[x][y]=='#') q.push(node{x,y,1}); else q.push(node{x,y,0}); vis[x][y]=1; while(!q.empty()) { top=q.top(); q.pop(); s[ord][top.x][top.y]=top.door; for(int i=0; i<4; i++) { temp=top; temp.x=top.x+to[i][0]; temp.y=top.y+to[i][1]; if(judge(temp.x,temp.y)) { if(mmp[temp.x][temp.y]=='#') temp.door++; q.push(temp); vis[temp.x][temp.y]=1; } } } return ; } int main() { scanf("%d",&t); while(t--) { memset(s,inf,sizeof(s)); ans=inf; c=x[0]=y[0]=0; scanf("%d%d",&n,&m); memset(mmp,'.',sizeof(mmp)); for(int i=1; i<=n; i++) { getchar(); for(int j=1; j<=m; j++) { scanf("%c",&mmp[i][j]); if(mmp[i][j]=='$') { x[++c]=i; y[c]=j; } } } for(int i=0; i<3; i++) bfs(i,x[i],y[i]); for(int i=0; i<=n; i++) for(int j=0; j<=m; j++) { if(mmp[i][j]=='*'||s[0][i][j]==inf||s[1][i][j]==inf||s[2][i][j]==inf)continue; if(mmp[i][j]=='#') ans=min(ans,s[0][i][j]+s[1][i][j]+s[2][i][j]-2); else ans=min(ans,s[0][i][j]+s[1][i][j]+s[2][i][j]); } printf("%d\n",ans); } return 0; }
J - Jailbreak Gym - 100625J -搜索+枚举交点
最新推荐文章于 2019-02-16 09:56:02 发布