Traffic Lights

题目大意:有一个城市的路线图,有N个交叉点,每两个交叉点之间只有一条路,现在想从交点u去交点v,不过这个路的交通比较特别,每个路都有一个交通灯,灯有两种颜色,蓝色和紫色,例如一条路线在交点s,t之间,如果想从s走到t,那么只有等s和t的交通灯的颜色一致的时候才可以从s走,求出来从u到v的最短时间。

分析:比较明显能看出来是一个最短路问题,不过里面夹杂的这个交通灯比较恶心,要随时能求出来两点点下一个相同颜色的时间,如果使用时间去枚举无疑是个比较笨的方法,注意到有个剩余时间,并且交通灯的每种颜色存在的最大值是100,所以可以判断出,一定会有重复情况出现,比如s剩余a,t剩余b,这种状态再次出现不会超过200次蓝紫灯循环,所以只需要枚举200次即可,如果还是找不带相同颜色,那么就说明这条路不能行走。ps.时间内存都比较小,边数比较多,所以邻接矩阵比连接表更省内存,注意有可能会有重边的情况。

代码如下:

=========================================================================================================================

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = 307;
const int oo = 1e9+7;

struct Junction
{
    int op;///等于0是B, 等于1代表P
    int Last;///剩余时间
    int t[2];///两种灯的转换时间

    Junction NewOp(int time)
    {///time时刻的状态
        Junction res;
        if(time >= Last)
        {///当前时间大于剩余时间,等于的时候也需要转变成下一个灯
            time -= Last;
            time %= (t[0]+t[1]);

            if(time >= t[op^1])
            {
                res.op = op;
                res.Last = t[op] - (time-t[op^1]);
            }
            else
            {
                res.op = op^1;
                res.Last = t[op^1]-time;
            }
        }
        else
        {
            res.op = op;
            res.Last = Last - time;
        }

        res.t[0] = t[0], res.t[1] = t[1];

        return res;
    }
    int SameColor(Junction a, Junction b)
    {///两个路灯下个相同颜色最少需要时间,-1表示不可能相同
     ///因为中间涉及到值得改变,所以不使用指针
        int i, time=0;

        for(i=0; i<200; i++)
        {
            if(a.op == b.op)
                return time;
            else if(a.Last >= b.Last)
            {
                time += b.Last;
                a.Last -= b.Last;
                b.Last = 0;
            }
            else if(a.Last < b.Last)
            {
                time += a.Last;
                b.Last -= a.Last;
                a.Last = 0;
            }

            if(a.Last == 0)
            {
                a.op ^= 1;
                a.Last = a.t[a.op];
            }
            if(b.Last == 0)
            {
                b.op ^= 1;
                b.Last = b.t[b.op];
            }
        }

        return -1;
    }
};

Junction p[MAXN];///交叉点
int N;///交叉点个数
int G[MAXN][MAXN];

void Dij(int start, int end)
{
    int dist[MAXN], path[MAXN]={0};
    int visit[MAXN]={0};

    for(int i=1; i<=N; i++)
        dist[i] = oo;
    dist[start] = 0;

    for(int t=0; t<N; t++)
    {
        int index=start, Min=oo;

        for(int i=1; i<=N; i++)
        {
            if(visit[i] == false && dist[i] < Min)
            {
                Min = dist[i];
                index = i;
            }
        }

        if(visit[index])
            break;
        visit[index] = true;

        Junction u = p[index].NewOp(dist[index]), v;

        for(int i=1; i<=N; i++)
        {
            if(!visit[i] && G[index][i] != oo && dist[i]>dist[index]+G[index][i])
            {
                v = p[i].NewOp(dist[index]);
                int time = u.SameColor(u, v);

                if(time != -1 && dist[i] > dist[index]+G[index][i]+time)
                {
                    dist[i] = dist[index] + G[index][i] + time;
                    path[i] = index;
                }
            }
        }
    }

    if(dist[end] == oo)
        printf("0
");
    else
    {
        printf("%d
", dist[end]);

        int k=0, ans[MAXN];

        while(end)
        {
            ans[k++] = end;
            end = path[end];
        }

        for(int i=k-1; i>=0; i--)
            printf("%d%c", ans[i], i==0?'
':' ');
    }
}

int main()
{
    int M, start, end;
    char s[10];

    scanf("%d%d%d%d", &start, &end, &N, &M);

    for(int i=1; i<=N; i++)
    {
        scanf("%s%d%d%d", s, &p[i].Last, &p[i].t[0], &p[i].t[1]);
        p[i].op = (s[0]=='B' ? 0 : 1);
    }

    int u, v, len;

    for(int i=1; i<=N; i++)
    for(int j=1; j<=N; j++)
        G[i][j] = oo;

    while(M--)
    {
        scanf("%d%d%d", &u, &v, &len);
        G[u][v] = G[v][u] = min(G[u][v], len);
    }

    Dij(start, end);

    return 0;
}
原文地址:https://www.cnblogs.com/liuxin13/p/4803450.html