[暑假集训]开训复健练习赛:B

#include<iostream>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#define DEBUG if(  1  )//是否输出调试用信息
using namespace std;
int W,H;
int time[2][205][205];
int stack[2000][2],stalen;
int tstack[2000][2],tstalen;
char map[205][205];
int px[2],py[2];//分别为Y与M的位置
int tx[205*201],ty[205*201],tn;//目标的位置
int mint;
int TOX[4]={1,0,-1,0},TOY[4]={0,-1,0,1};
void f(int pn,int T){
    stalen--;
    int x=stack[stalen][0],y=stack[stalen][1];
    if(x<0 || y<0 || x>=W || y>=H)return;
    if(map[y][x]=='#')return;
    DEBUG cout<<T%10;//测试输出,可以看出运行了多少次
    if(time[pn][y][x]>=0){
        //说明此位置已添加入tstack
        if(time[pn][y][x]>T){
            //此位置的T要尽量小
            time[pn][y][x]=T;
        }
    }else{
        time[pn][y][x]=T;
        //记录到达此位置所需T
        for(int i=0;i<4;i++){
            //四个方向加入tstack
            tstack[tstalen][0]=x+TOX[i];
            tstack[tstalen][1]=y+TOY[i];
            tstalen++;
        }
    }
}
int main(){
    while(cin>>H>>W){
        memset(time,-1,2*205*205*4);
        
        tn=0;mint=-5;
        for(int i=0;i<W*H;i++){
            //读取地图数据
            int yy=i/W,xx=i%W;
            cin>>map[yy][xx];
            if(map[yy][xx]=='Y'){
                px[0]=i%W;py[0]=i/W;
            }else if(map[yy][xx]=='M'){
                px[1]=i%W;py[1]=i/W;
            }else if(map[yy][xx]=='@'){
                tx[tn]=i%W;ty[tn]=i/W;tn++;
            }
        }
        int TT=0;
        for(int thep=0;thep<2;thep++){
            //以Y或M的位置作为初始点
            stack[0][0]=px[thep];TT=0;
            stack[0][1]=py[thep];stalen=1;
            //两次广度优先
            while(stalen>0){
                while(stalen>0){
                    f(thep,TT);//遍历stack
                }
                TT++;//下一次行动
                //交换tstack与stack情况
                stalen=tstalen;
                for(int i=0;i<tstalen;i++){
                    stack[i][0]=tstack[i][0];
                    stack[i][1]=tstack[i][1];
                }tstalen=0;
            }
        }
        DEBUG{cout<<endl;
            int ntn=-1;while(++ntn<2){
                //输出全地图计算后需要走的步数
                for(int i=0;i<W*H;i++){
                    int ttt=time[ntn][i/W][i%W];
                    if(ttt<0)
                        cout<<"#";
                    else 
cout<<"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[ttt%(10+26*2)];
                    if(i%W==W-1)cout<<endl;
                }
                cout<<endl;
            }
        }
        for(int i=0;i<tn;i++){
            //找最小的
            int t0m=time[0][ty[i]][tx[i]],
                t1m=time[1][ty[i]][tx[i]];
            DEBUG {
                cout<<tx[i]<<" "<<ty[i]<<"->"
                    <<t0m<<"+"<<t1m<<"="<<t0m+t1m<<endl;
            }
            if(t0m>=0 && t1m>=0){
                //mint初始为-5,不能筛出负数给他,也不能让他保留为负数
                if(mint>=0)
                    mint=min(mint,t0m+t1m);
                else
                    mint=t0m+t1m;
            }

        }
        DEBUG cout<<mint<<"*11=";
        cout<<mint*11<<endl;
    }
    return 0;
}

https://vjudge.net/contest/382410#problem/B

原文地址:https://www.cnblogs.com/forwhat00/p/13284791.html