[USACO11OPEN] Corn Maze S

给定一个 (N imes M) 地图,每个格子可能是空地、墙、出口、起点,或者是一副瞬移管道的两端。当你达到瞬移管道一端所在的格子时,就会自动瞬移到另一端。从一个空地移到四连通的另一个空地需要 (1) 时间。瞬移不需要时间。求从起点到出口的最小时间。(N leq 300, M leq 300)

Solution

难度:L3

拆点建图跑最短路即可

每个点拆成入点和出点,其中普通点的入点和出点直接相连,瞬移管道的入点和出点不想连,管道一端的入点连到管道另一端的出点,费用为 (0)

#include <bits/stdc++.h>
#define reset3f(x) memset(x,0x3f,sizeof x)
using namespace std;
namespace sp {
const int N=4e+6+5;
vector<pair<int,int> > g[N];
int v0=1,d[N];
void make(int t1,int t2,int t3) {
    g[t1].push_back(make_pair(t2,t3));
}
void solve() {
    priority_queue<pair<int,int> > qu;
    reset3f(d);
    d[v0]=0;
    qu.push(make_pair(0,v0));
    while(qu.size()) {
        int p=qu.top().second,r=qu.top().first;
        qu.pop();
        if(r+d[p]) continue;
        for(int i=0;i<g[p].size();i++) {
            int q=g[p][i].first,w=g[p][i].second;
            if(d[q]>d[p]+w) {
                d[q]=d[p]+w;
                qu.push(make_pair(-d[q],q));
            }
        }
    }
}
}
using sp::make;
using sp::solve;
using sp::d;
using sp::v0;

const int N = 305;
const int dx[4] = {-1,1,0,0};
const int dy[4] = {0,0,1,-1};

int n,m;
char s[N][N];

int id(int i,int j) {
    return m*(i-1)+j;
}

int idx(int i,int j) {
    return m*n+m*(i-1)+j;
}

int ok(int i,int j) {
    return i>0 && j>0 && i<=n && j<=m && s[i][j]!='#';
        //(s[i][j]=='.' || s[i][j]=='@' || s[i][j]=='=');
}

int r1[27],c1[27],r2[27],c2[27];

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>s[i]+1;
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            if(ok(i,j)) {
                if(s[i][j]<'A' || s[i][j]>'Z')
                    make(id(i,j),idx(i,j),0);
                if(ok(i-1,j)) make(idx(i,j),id(i-1,j),1);
                if(ok(i+1,j)) make(idx(i,j),id(i+1,j),1);
                if(ok(i,j-1)) make(idx(i,j),id(i,j-1),1);
                if(ok(i,j+1)) make(idx(i,j),id(i,j+1),1);
            }
            if(s[i][j]>='A' && s[i][j]<='Z') {
                if(r1[s[i][j]-'A']==0) {
                    r1[s[i][j]-'A']=r2[s[i][j]-'A']=i;
                    c1[s[i][j]-'A']=c2[s[i][j]-'A']=j;
                }
                else {
                    r2[s[i][j]-'A']=i;
                    c2[s[i][j]-'A']=j;
                }
            }
        }
    }
    for(int i=0;i<26;i++) {
        if(r1[i]) {
            make(id(r1[i],c1[i]),idx(r2[i],c2[i]),0);
            make(id(r2[i],c2[i]),idx(r1[i],c1[i]),0);
        }
    }
    int i1,j1,i2,j2;
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            if(s[i][j]=='@') i1=i,j1=j;
            if(s[i][j]=='=') i2=i,j2=j;
        }
    }
    v0=id(i1,j1);
    solve();
    cout<<d[id(i2,j2)];
}

原文地址:https://www.cnblogs.com/mollnn/p/12490590.html