• SGU103+POJ 1158 最短路/dp


    题意:一个无向图,求起点到终点最少时间,限制:每个路口有灯,要灯颜色一样才能过去,灯之有俩种颜色,周期
    变化,给定每个灯初态,时间。
    思路:开始就想到直接DP,方程dp[k]=dp[i]+distance[i][k]+waittime(i,k),于是天真得BFS敲了这个,
    SB啊!有些点松弛了,之后它又被松弛,它便还可以松弛别人啊!否则世界上最短路O(n)的算法就诞生了!
    所以,一旦某个点被松弛了,它便可以再入队,啊哈?这不就是SPFA吗!!我去,这次是对SPFA更加理解了,
    自己想法竟然遇上经典算法了。其本质就是DP,状态的转移,初期放的错误是:没有所有点都对k松弛,而k已经出队
    (对别人松弛过了)。
    这题较麻烦的地方是计算等待的时间,细节模拟,我是先算出当前时间,路口的状态,再讨论下接下来等待的
    时间。
    未1A:
    复制差不多代码的时候2个数据没有改,导致错误。打印路劲的时候开始用栈(因为记录是逆序的)。导致爆内存,
    以后尽量不要用栈记录!
    改进:其实写等待函数可以分俩个函数,每个点当前状态一个,加一个算时间的函数。那样代码就减少很多,

    并且也清晰很多。


    #include<iostream>
    #include<queue>
    #include<cstdio>
    using namespace std;
    const int inf=0x3f3f3f3f;
    struct nodes
    {
        int remain;
        char initial;
        int tb;
        int tp;
    };
    nodes node[310];
    int n,m;int s,l;
    int times=0;
    int e[50000][3];int head[310];int nume=0;
    void inline addedge(int from,int to, int w)
    {
        e[nume][0]=to;e[nume][1]=head[from];head[from]=nume;
        e[nume++][2]=w;
        e[nume][0]=from;e[nume][1]=head[to];head[to]=nume;
        e[nume++][2]=w;
    }
    int dp[310];
    void readin()
    {
        cin>>s>>l>>n>>m;
       for(int i=1;i<=n;i++)
       {
           head[i]=-1;
           dp[i]=inf;
           cin>>node[i].initial>>node[i].remain>>node[i].tb>>node[i].tp;
       }
       int from,to,w;
       for(int i=0;i<m;i++)
       {
           cin>>from>>to>>w;
           addedge(from,to,w);
       }
    }
    char inline change(char s)  //变色
    {
        if(s=='B')return 'P';
        return 'B';
    }
    int gettime(int nowt,int u,int v) //计算等待时间
    {
        int reu=0,rev=0;               //模拟出当前灯还剩余多少时间
        int nowu=nowt-node[u].remain;  //先减去开始的剩余时间
        char cv=node[v].initial,cu=node[u].initial;//cu,cv模拟出当前灯
        if(nowu==0)         //干好
        {
            if(node[u].initial=='B'){cu='p';reu=node[u].tp;}
            else {cu='B';reu=node[u].tb;}
        }
        else if(nowu<0)   //剩余时间还有
        {
            reu=node[u].remain-nowt;
        }
        else                 
        {
            int re=nowu%(node[u].tb+node[u].tp);//多余
            if(re==0)cu=change(cu);         //讨论略繁琐
            else if(cu=='B')
            {
                  if(re<node[u].tp)
                     cu=change(cu);
            }
            else if(cu=='P')
            {
                if(re<node[u].tb)
                    cu=change(cu);
            }
            if(cu=='P')
            {
                reu=(node[u].tb+node[u].tp)-re-node[u].tb;
                if(node[u].initial=='P')reu+=node[u].tb;
            }
            else if(cu=='B')
            {
                reu=(node[u].tb+node[u].tp)-re-node[u].tp;
                if(node[u].initial=='B')reu+=node[u].tp;
            }
        }
         int nowv=nowt-node[v].remain;
        if(nowv==0)
        {
            if(node[v].initial=='B'){cv='p';rev=node[v].tp;}
            else {cv='B';rev=node[v].tb;}
        }
        else if(nowv<0)
        {
            rev=-nowv;
        }
         else
        {
            int re=nowv%(node[v].tb+node[v].tp);
            if(re==0)cv=change(cv);
            else if(cv=='B')
            {
                  if(re<node[v].tp)
                     cv=change(cv);
            }
            else if(cv=='P')
            {
                if(re<node[v].tb)
                  cv=change(cv);
            }
              if(cv=='P')
            {
                rev=(node[v].tb+node[v].tp)-re-node[v].tb;
                if(node[v].initial=='P')rev+=node[v].tb;
            }
            else if(cv=='B')
            {
                rev=(node[v].tb+node[v].tp)-re-node[v].tp;
                if(node[v].initial=='B')rev+=node[v].tp;
            }
        }
        if(cu==cv)return 0;
        else
        {
              if(reu>rev)
                  return rev;
              if(reu<rev)
                  return reu;
              else
               {
                   cu=change(cu);
                   cv=change(cv);
                   if(cu=='B')
                   {
                       if(node[u].tb<node[v].tp)
                           return reu+node[u].tb;
                       else if(node[u].tb>node[v].tp)
                           return reu+node[v].tp;
                       else
                          {
                              if(node[u].tp<node[v].tb)
                                   return reu+node[u].tb+node[u].tp;
                              else if(node[u].tp>node[v].tb)
                                  return reu+node[v].tp+node[v].tb;
                              else
                                  return   inf;
                          }
                   }
                    else if(cu=='P')
                   {
                       if(node[u].tp<node[v].tb)
                           return reu+node[u].tp;
                       else if(node[u].tp>node[v].tb)
                           return reu+node[v].tb;
                       else
                          {
                              if(node[u].tb<node[v].tp)
                                   return reu+node[u].tp+node[u].tb;
                              else if(node[u].tb>node[v].tp)
                                  return reu+node[v].tb+node[v].tp;
                              else
                                  return   inf;
                          }
                   }
               }
        }
    }
    int vis[310];
    int fa[310];
    int way[310];
    queue<int>q;
    int main()
    {
        readin();
        q.push(s);
        dp[s]=0;
        while(!q.empty())         //spfa
        { 
            int cur=q.front();
            q.pop();
            vis[cur]=0;
            for(int i=head[cur];i!=-1;i=e[i][1])
            {
                int v=e[i][0];
                int getv=dp[cur]+e[i][2];
                getv+=gettime(dp[cur],cur,v);
                if(vis[v]==0&&getv<dp[v])
                  {
                      q.push(v);
                      vis[v]=1;
                  }
                if(getv<inf&&getv<dp[v])
                {
                    dp[v]=getv;
                    fa[v]=cur;  //跟新时候记录父节点,不可记录子节点法,容易想到反例。
                }
            }
        }
        if(dp[l]>=inf){cout<<0<<endl;return 0;}  //无解
        cout<<dp[l]<<endl;
        int i=l;
        int num=0;
        while(i!=s)
        {
           way[num++]=i;
            i=fa[i];
        }
        way[num]=i;
        for(int j=num;j>=0;j--)
        {
            if(j==0)printf("%d
    ",way[j]);
            else printf("%d ",way[j]);
        }
     return 0;
    }
    


  • 相关阅读:
    (元)黄公望---富春山居图(中国十大传世名画之八) 高清图下载
    Bloom Filter 原理与应用
    开始我的 JNI 入门吧
    javaScript的使用
    hash定义
    POJ3169 Layout(差分约束系统)
    青蛙的约会
    POJ 3414 Pots ( BFS , 打印路径 )
    你真的理解Java的this和super吗?
    十款优秀的在线JavaScript工具介绍
  • 原文地址:https://www.cnblogs.com/yezekun/p/3925726.html
Copyright © 2020-2023  润新知