usaco2.4.3穿越栅栏(最短路)

这题一开始就建了一个4维数组,结果交上去超出空间了,郁闷了好一会儿,后来想到,一块地方只可能有四个地方与其有路,所以只需要判断它周围的4块区域就可以了,方法安最短路Dijkstra算法就可以了。至于这个算法的介绍,刘汝佳的太短小精悍了,不建议看,还是附上正常人的代码吧:

//函数返回从节点s到节点e的最短路,共n个节点
long dijk(long s,long e)
{
     const long infi=999999999;
 
     long dis[n]={0};
     bool used[n]={false};
     long min,next;
     memset(dis,255,sizeof(dis));
     dis[s]=0;
 
     for(long i=1;i<=n;i++)
        {
         min=infi;
         for(long j=1;j<=n;j++)
            if(!used[j] && dis[j]!=-1 && dis[j]<min)
              {
               min=dis[j];
               next=j;
              }
         if(min!=infi)
           {
            used[next]=true;
            for(long j=1;j<=n;j++)
               if(!used[j] && map[next][j]!=-1 && (dis[j]>map[next][j]+dis[next] || dis[j]==-1))
                 dis[j]=map[next][j]+dis[next];
           }
        }
 
     return dis[e];
}
接下来是这道题的代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
using namespace std;
int map[110][40],w,h;
struct aaaa{int x;int y;}door[2];
void aaa(int x,int y,int k);
int dis[2][110][40];
bool key[2][110][40];
int main()
{
    cin>>w>>h;
    int l1=0;
    char lll;
    scanf("%c",&lll);
    for(int i=1;i<=h;i++){
        char ch,ch1;
        for(int j=1;j<=w;j++){
        scanf("%c%c",&ch1,&ch);
        if(ch==' '){map[i][j]+=8;map[i-1][j]+=2;if(i==1){door[l1].x=i;door[l1++].y=j;}}
        }
        scanf("%c%c",&ch1,&ch);
        for(int j=1;j<=w;j++){
        scanf("%c%c",&ch1,&ch);
        if(ch1==' '){map[i][j]+=4;map[i][j-1]+=1;if(j==1){door[l1].x=i;door[l1++].y=j;}}
        }
        scanf("%c%c",&ch1,&ch);
        if(ch1==' '){door[l1].x=i;door[l1++].y=w;}
    }
    for(int i=1;i<=w+1;i++){
        if(l1==2)break;
        char ch,ch1;
         scanf("%c%c",&ch1,&ch);
        if(ch==' '){door[l1].x=h;door[l1].y=i;}
    }
    for(int i=0;i<=1;i++)
    {
        aaa(door[i].x,door[i].y,i);
    }
    for(int i=1;i<=h;i++)
    for(int j=1;j<=w;j++)
       {
           dis[0][i][j]=min(dis[0][i][j],dis[1][i][j]);
       }
    int kkk=0;
    for(int i=1;i<=h;i++)
        for(int j=1;j<=w;j++)
    {
        if((i!=door[0].x||j!=door[0].y)&&(i!=door[1].x||j!=door[1].y))
            kkk=max(kkk,dis[0][i][j]);
    }
    cout<<kkk+1<<endl;
return 0;
}
void aaa(int x,int y,int k)
{
    aaaa next;
    for(int i=1;i<=h;i++)
        for(int j=1;j<=w;j++)
        dis[k][i][j]=-1;
    dis[k][x][y]=0;
    for(int kk=1;kk<=w*h;kk++)
    {
        int mins=999999;
        for(int i=1;i<=h;i++)
            for(int j=1;j<=w;j++)
            if(!key[k][i][j]&&dis[k][i][j]!=-1&&dis[k][i][j]<mins){
             mins=dis[k][i][j];
             next.x=i;
             next.y=j;
        }
        if(mins!=999999)
        {
            key[k][next.x][next.y]=true;
            for(int j=1;j<=8;j*=2)
            if(j==1)
            {if(!key[k][next.x][next.y+1]&&map[next.x][next.y]&1&&(dis[k][next.x][next.y+1]>dis[k][next.x][next.y]+1||dis[k][next.x][next.y+1]==-1))
                dis[k][next.x][next.y+1]=dis[k][next.x][next.y]+1;}
            else if(j==2)
            {if(!key[k][next.x+1][next.y]&&map[next.x][next.y]&2&&(dis[k][next.x+1][next.y]>dis[k][next.x][next.y]+1||dis[k][next.x+1][next.y]==-1))
                dis[k][next.x+1][next.y]=dis[k][next.x][next.y]+1;}
            else if(j==4)
            {if(!key[k][next.x][next.y-1]&&map[next.x][next.y]&4&&(dis[k][next.x][next.y-1]>dis[k][next.x][next.y]+1||dis[k][next.x][next.y-1]==-1))
                dis[k][next.x][next.y-1]=dis[k][next.x][next.y]+1;}
            else if(j==8)
            {if(!key[k][next.x-1][next.y]&&map[next.x][next.y]&8&&(dis[k][next.x-1][next.y]>dis[k][next.x][next.y]+1||dis[k][next.x-1][next.y]==-1))
                dis[k][next.x-1][next.y]=dis[k][next.x][next.y]+1;}
        }
   }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值