zoukankan      html  css  js  c++  java
  • sgu 103 Traffic Lights 解题报告及测试数据

    103. Traffic Lights

    Time limit per test: 0.25 second(s)

    Memory limit: 4096 kilobytes

    题解:

    1、其实就是求两点间的最短路,不过加了交通灯的限制,使得两点间的所需时间并不只是由路程决定。

    2、只有一条路两个端点的交通灯颜色相同时,该路才可以通过。但是这有一种情况,当两个交通灯处于不同颜色时,经过t时间,交通灯又恰好处于不同颜色,由于最初有一个颜色预变时间riC以及蓝色tiB、紫色周期tiP ,那么就需要计算交通灯变化时间的函数递归两次(函数执行三次),如果递归两次后还处于不同颜色,那么可以断定该交通灯蓝、紫色周期相反,不能通过。例如B 32 32 13和P 32 96 49 经过32s后变成P 13 32 13 和B 96 96 49(紫色变为蓝色后,将过tiB时间即96变为紫色),那么很显然,此时再过13s即可变为相同颜色。那么这两点所需等待交通灯时间为13+32=45s。一开始只都递归了一次,在test 6的时候挂了,所以计算等待函数,应递归两次。

    3、最短路算法,dijkstra算法的复杂度为O(N^2),最后提交的结果是用时31ms。当然求最短路,dfs也是可以的,但是经过尝试,dfs在test 2 就TLE了。

    以下是代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <climits>
    #include <cstdlib>
    using namespace std;
    int st,ed;
    int N,M;
    int c[2][2];          //0 b,1 p;
    int a[310][310];   // 记录输入的无向图
    int Min=INT_MAX;    // 最大值
    struct Light{    // 记录输入的交通灯的信息
        int c, t,b,p;// c输入的颜色,t变换时间,b,p周期
    }L[310];        
    void input(){  // 输入
        int t1,t2;
        char str[3];
        scanf("%d%d%d%d",&st,&ed,&N,&M);
        for(int i=1;i<=N;i++){
            scanf("%s%d%d%d",str,&L[i].t,&L[i].b,&L[i].p);
            L[i].c= str[0] =='B'? 0 :1;
        }
        for(int i=1;i<=N;i++)
            for(int j=1;j<=N;j++)
                if(i!=j)a[i][j]=Min;
        for(int i=1;i<=M;i++){
            scanf("%d%d",&t1,&t2);
            scanf("%d",&a[t1][t2]);
            a[t2][t1]=a[t1][t2];
        }
    }
    void calnow(int v,int pre,int k){ //计算第v个节点在过了pre时间后的颜色
        if(pre<L[v].t){
            c[k][0] = L[v].c;
            c[k][1] = L[v].t-pre;
            return ;
        }
        int mo = (pre - L[v].t)%(L[v].b+L[v].p);
        switch(L[v].c){
        case 0 :
            if(mo < L[v].p){
                c[k][0]=1;c[k][1]=L[v].p - mo;
            }else{
                c[k][0]=0;c[k][1]=L[v].b - (mo - L[v].p);
                 }break;
        case 1 :
            if(mo < L[v].b){
                c[k][0]=0;c[k][1]=L[v].b - mo;
            }else{
                c[k][0]=1;c[k][1]=L[v].p - (mo - L[v].b);
                 }break;
        }
    }
    int caldelay(int v,int u,int pre,int f){ // 计算如果走v—u需要多长时间
        calnow(v,pre,0);
        calnow(u,pre,1);
        if(c[0][0] == c[1][0])return 0;
        int t1 = c[0][1],t2=c[1][1];
        if(t1 == t2){
            if(f==2)return -1;else {
                int  t = caldelay(v,u,pre+t1,f+1);//递归两次,才能确定能否通行。
                if(t==-1)return -1;
                return t+t1;
            }
        }
        return t1<t2 ? t1:t2;
    }
    void dijkstra()// 狄杰斯特拉算法,求最短路
    {
        int v=st;
        int d[310],pr[310],vis[310];
        memset(vis,0,sizeof(vis));
        memset(pr,0,sizeof(pr));
        for(int i=0;i<310;i++)d[i]=Min;
        for(int i=1;i<=N;i++)
        if(a[v][i]<Min){
            d[i]=a[v][i]+caldelay(v,i,0,0);
            pr[i]= v;
        }else{ d[i]=Min;pr[i]=0;}
        vis[v]=1;pr[v]=0;
        for(int i=1;i<=N;i++){
            int k=0,m=Min;
            for(int j=1;j<=N;j++)
                if(!vis[j] && d[j]< m)m = d[k=j];
            if(k==0)break;
            vis[k]=1;
            for(int j=1;j<=N;j++)
            if(k!=j && a[k][j]!=Min){
                int t = caldelay(k,j,d[k],0);
                if(t==-1)continue;
                if(d[j]>d[k]+t+a[k][j]){
                    d[j] = d[k]+t+a[k][j];
                    pr[j]=k;
                }
            }
        }
        if(st==ed)printf("0
    %d
    ",st);
        else if(d[ed]==Min)printf("0
    ");
        else{
            printf("%d
    ",d[ed]);
            int t =ed,path[310],k=0;
            while(pr[t]){ path[++k]=pr[t];t =pr[t];}
            path[0]=ed;
            for(int i=k;i>=0;i--)
                printf("%d ",path[i]);
            printf("
    ");
        }
    }
    int main(){
        //freopen("1.in","r",stdin);
        input();
        dijkstra();
    }

    以下是测试数据:

    sample input

    10 2

    17 2

    B 42 5 96 

    B 47 51 60 

    B 49 28 70 

    B 71 77 17 

    P 95 97 59 

    B 5 56 99 

    B 82 56 74 

    P 97 60 15 

    P 78 32 54 

    B 3 20 55 

    B 84 8 46 

    P 93 32 64 

    B 25 11 99 

    B 73 33 15 

    B 59 58 70 

    P 85 61 61 

    P 53 13 43 

    6 12 17

    15 12 75

     

    4 4

    13 11

    P 79 49 75 

    B 87 71 22 

    B 11 79 30 

    P 91 1 72 

    B 50 59 84 

    B 88 72 41 

    B 85 21 47 

    B 66 11 100 

    B 39 21 28 

    B 42 59 42 

    P 4 47 2 

    B 41 36 48 

    P 97 60 25 

    11 3 38

    10 10 57

    7 6 86

    5 9 69

    7 9 17

    5 9 77

    4 10 13

    6 3 79

    2 8 78

    3 12 90

    13 9 37

     

    4 5

    5 20

    P 35 52 3 

    B 10 82 91 

    B 29 81 35 

    P 85 62 64 

    B 87 27 12 

    3 5 39

    3 4 98

    5 3 19

    4 2 4

    5 1 36

    4 1 94

    4 2 12

    3 4 41

    5 2 90

    4 2 2

    3 1 71

    3 1 33

    5 1 94

    1 5 67

    1 4 65

    4 1 54

    4 5 16

    3 3 22

    1 2 19

    2 5 76

     

    1 3

    4 17

    B 73 40 10 

    P 38 5 50 

    B 46 64 69 

    P 93 88 94 

    1 3 91

    3 4 72

    2 3 14

    4 3 46

    3 2 5

    2 2 52

    2 3 26

    1 3 93

    1 1 75

    4 4 84

    4 1 39

    2 3 63

    3 2 10

    4 1 70

    1 1 71

    2 4 75

    1 2 34

    sample output

    0

     

    0

    4

     

    71

    4 2 1 5

     

    77

    1 2 3

  • 相关阅读:
    排球训练营
    TP5中手机端和PC端判断
    N550JV无法休眠,休眠自动重启的原因及解决方法
    HTML标签全称
    HTML思维导图
    HTML基础
    Web项目流程
    VsCode使用之HTML 中 CSS Class 智能提示
    MyEclipse崩溃 Java was started but returned exit code=-1073740791
    Python 类的特殊成员方法
  • 原文地址:https://www.cnblogs.com/gzdaijie/p/4296808.html
Copyright © 2011-2022 走看看