zoukankan      html  css  js  c++  java
  • [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)];
    }
    
    
  • 相关阅读:
    2017-3-13 SQL server 表连接
    2017-3-13 SQL server 函数(聚合函数,数学函数,字符串函数,转换函数,时间日期函数)
    2017-3-10 SQL server T-sql语句 高级查询
    2017-3-10 SQL server 数据库 T--SQL语句
    layer框架使用的问题汇总
    pulic——功能性(自己写完测试的)list转树
    bootstrap的datetimepicker使用(1.将默认的英文设置为中文2.选择日月年的时候记录之前的操作)
    临时笔记0318
    最简单的多线程代码,一句话就可以使用
    scrollview滑动到某区域执行某种方法
  • 原文地址:https://www.cnblogs.com/mollnn/p/12490590.html
Copyright © 2011-2022 走看看