1. 程式人生 > >Jailbreak 個人訓練賽

Jailbreak 個人訓練賽

https://vj.e949.cn/5e9d1ef965fc5f2bb34f0d3ff5e7eca4?v=1542378645 j題

題意:兩個人逃出監獄的最小開門數,門開啟後不會關閉。

思路:對圖加邊,預設空地,然後最優為兩人最後會和一起出去。以(0,0)和兩個人的起點搜三遍存圖。遍歷所有點假設這是集結點求最小開門數。

搜圖的時用優先佇列維護最小開門的點,普通佇列維護的是步數最小。

#include <bits/stdc++.h>
#include<stdio.h>
#define inf 0x3f3f3f3f
using namespace std;
struct code
{
    int x,y,di;
} tt,tep;
bool operator <(code a,code b)
{
    return a.di>b.di;
}
int dap[105][105],n,m;
char s;
int dist1[105][105],dist2[105][105],dist3[105][105];
int nx[4][2]= {1,0,0,1,-1,0,0,-1};
bool ok(int x,int y)
{
    if(x>=0&&x<=n+1&&y>=0&&y<=m+1)
        return true;
    else
        return false;
}
void dfs1(int x,int y)
{
    int visit[105][105];
    memset(visit,0,sizeof(visit));
    priority_queue<code>p;
    tt.x=x;
    tt.y=y;
    p.push(tt);
    dist1[x][y]=0;
    visit[x][y]=1;
    while(!p.empty())
    {
        tt=p.top();
        p.pop();
        for(int i=0; i<4; i++)
        {
            int tx=tt.x+nx[i][0],ty=tt.y+nx[i][1];
            if(!ok(tx,ty)||visit[tx][ty]==1)
                continue;
            if(dap[tx][ty]==1||dap[tx][ty]==0)
            {
                tep.x=tx;
                tep.y=ty;
                if(dap[tx][ty]==1)
                    dist1[tx][ty]=dist1[tt.x][tt.y]+1;
                else
                    dist1[tx][ty]=dist1[tt.x][tt.y];
                tep.di=dist1[tx][ty];
                visit[tx][ty]=1;
                p.push(tep);
            }
        }
    }
}
void dfs2(int x,int y)
{
    int visit[105][105];
    memset(visit,0,sizeof(visit));
    priority_queue<code>p;
    tt.x=x;
    tt.y=y;
    p.push(tt);
    dist2[x][y]=0;
    visit[x][y]=1;
    while(!p.empty())
    {
        tt=p.top();
        p.pop();
        for(int i=0; i<4; i++)
        {
            int tx=tt.x+nx[i][0],ty=tt.y+nx[i][1];
            if(!ok(tx,ty)||visit[tx][ty]==1)
                continue;
            if(dap[tx][ty]==1||dap[tx][ty]==0)
            {
                tep.x=tx;
                tep.y=ty;
                if(dap[tx][ty]==1)
                    dist2[tx][ty]=dist2[tt.x][tt.y]+1;
                else
                    dist2[tx][ty]=dist2[tt.x][tt.y];
                tep.di=dist2[tx][ty];
                visit[tx][ty]=1;
                p.push(tep);
            }
        }
    }
}
void dfs3(int x,int y)
{
    int visit[105][105];
    memset(visit,0,sizeof(visit));
    priority_queue<code>p;
    tt.x=x;
    tt.y=y;
    p.push(tt);
    dist3[x][y]=0;
    visit[x][y]=1;
    while(!p.empty())
    {
        tt=p.top();
        p.pop();
        for(int i=0; i<4; i++)
        {
            int tx=tt.x+nx[i][0],ty=tt.y+nx[i][1];
            if(!ok(tx,ty)||visit[tx][ty]==1)
                continue;
            if(dap[tx][ty]==1||dap[tx][ty]==0)
            {
                tep.x=tx;
                tep.y=ty;
                if(dap[tx][ty]==1)
                    dist3[tx][ty]=dist3[tt.x][tt.y]+1;
                else
                    dist3[tx][ty]=dist3[tt.x][tt.y];
                tep.di=dist3[tx][ty];
                visit[tx][ty]=1;
                p.push(tep);
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(dap,0,sizeof(dap));
        int x=-1,y=-1,tx=-1,ty=-1;
        for(int i=1; i<=n; i++)
        {
            getchar();
            for(int j=1; j<=m; j++)
            {
                scanf("%c",&s);
                if(s=='*')
                    dap[i][j]=2;
                else if(s=='#')
                    dap[i][j]=1;
                else
                    dap[i][j]=0;
                if(s=='$')
                {
                    if(x==-1)
                    {
                        x=i;
                        y=j;
                    }
                    else
                    {
                        tx=i;
                        ty=j;
                    }
                }
            }
        }
        dfs1(0,0);
        dfs2(x,y);
        dfs3(tx,ty);
        int ans=inf;
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
                if(dap[i][j]==1)
                    ans=min(ans,dist1[i][j]+dist2[i][j]+dist3[i][j]-2);
                else if(dap[i][j]==0)
                    ans=min(ans,dist1[i][j]+dist2[i][j]+dist3[i][j]);
        }
        ans=min(ans,dist1[0][0]+dist2[0][0]+dist3[0][0]);
        printf("%d\n",ans);
    }
    return 0;
}