zoukankan      html  css  js  c++  java
  • TCO之旅

    TCO之旅

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 77  解决: 24
    [提交][状态][讨论版]

    题目描述

    我们的小强终于实现了他TCO的梦想了,爬进了TCO的全球总决赛,开始了他的 
    American之旅,去和TC的titan们去同场竞技去了,这可把小强给乐坏了。。。 
    由于在American人身地不熟,我们的小强遇到了很大的麻烦,他一下子找不到了比赛的地点,我们可以把交通网络这样进行简化。总共有n个城市,编号从0到n-1,我们的小强现在在标号为0的城市,他要到标号为n-1的城市去的。对于每个城市i,都有一个值cellprice[i]表示到这个城市的代价,如果是-1,就表示无法到达这个城市。在城市i中,存在着到城市i-1和城市i+1的直达车,代价分别为cellprice[i-1]和cellprice[i+1]。在某些城市之间又存在这特殊的城际班车。Entercell[i]表示第i条特殊的城际班车所在的起点城市,exitcell[i]表示第i条特殊的城际班车所在的终点城市。每次乘坐这种特殊的城市班车时所需的代价是price+x,这里的price是个定值,x表示你先前已经乘坐过特殊的城际班车的次数,当你乘坐特殊的城际班车到达某座城市i时,你就不需要花费cellprice[i]。 
    为了节省花费和时间,我们需要找出一条最优的乘车线路。当然,这个肯定难不倒我们的小强,毕竟是TCO总决赛的选手,这个简直是切菜的活。但现在他就来这里考考你,看你是否有进入TCO world final的能力。他要求首先花费要最少,在花费最少的前提下,要求乘坐的车的次数尽量的少。 

    输入

    每组四行:第一行有个1到50个大于等于-1的整数,即cellprice 
    第二行有0到50个整数 ,表示特殊的城际班车的出发点, 即entercell 
    第三行有0到50个整数, 表示上一行所对应的特殊的城际班车的终点, 即exitcell 
    第四行非负的整数表示 price 
    我们保证输入的数据是正确的,以上所有的整数均在-1到1000之间,并且出发点的cellprice肯定是非负的。 

    输出

    两个整数 ,分别表示最小的花费和在这种花费下的最小乘车次数,并用一个空格隔开。 如果无法到达终点,则输出-1 -1 ;

    样例输入

    4 2 1 0 5 6 0 3 0
    4 4 3 7 5 4 2 5 8 4
    3 5 0 5 4 5 0 8 3
    8

    样例输出

    14 6

    提示

    数据是分文件的,第二行和第三行可能是空行

     这个也是比较简单的,难就难在如何想到这个思想,最短路的点扩展成为两维,各层之间只有相互的点可以到达,然后相邻两层之间用特殊路径到达,这样建图即可。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<string>
      4 #include<algorithm>
      5 #include<cmath>
      6 #include<cstdio>
      7 #include<queue>
      8 using namespace std;
      9  
     10 typedef pair<int,int>fzy;
     11 const int INF=1e8+7,NN=107,MM=NN*NN;
     12  
     13 int n,m,a[NN],st[NN],ed[NN],price;
     14 int cnt,head[NN],rea[MM],next[MM],val[MM],dis[NN][NN],skp[NN][NN];
     15 bool flag[MM],stack[NN][NN];
     16 queue<fzy>p;
     17 string s;
     18  
     19 void add(int u,int v,int fee)
     20 {
     21     cnt++;
     22     next[cnt]=head[u];
     23     head[u]=cnt;
     24     rea[cnt]=v;
     25     val[cnt]=fee;
     26 }
     27 void init()
     28 {
     29     cnt=0;
     30     memset(head,-1,sizeof(head));
     31     getline(cin,s);
     32     int i=0;
     33     while (i<s.size())
     34     {
     35         int x=0,f=1;
     36         while ((s[i]<'0'||s[i]>'9')&&i<s.size()) {if (s[i]=='-') f=-1;i++;} 
     37         while (s[i]>='0'&&s[i]<='9'&&i<s.size()) x=x*10+s[i]-'0',i++;
     38         n++,a[n]=x*f;
     39     }
     40     getline(cin,s);
     41     i=0;
     42     while (i<s.size())
     43     {
     44         int x=0,f=1;
     45         while ((s[i]<'0'||s[i]>'9')&&i<s.size()) {if (s[i]=='-') f=-1;i++;} 
     46         while (s[i]>='0'&&s[i]<='9'&&i<s.size()) x=x*10+s[i]-'0',i++;
     47         m++,st[m]=x;
     48     }
     49     for (int i=1;i<=m;i++) 
     50         st[i]++;
     51     getline(cin,s);
     52     i=m=0;
     53     while (i<s.size())
     54     {
     55         int x=0;
     56         while (s[i]>='0'&&s[i]<='9') x=x*10+s[i]-'0',i++;
     57         while ((s[i]<'0'||s[i]>'9')&&i<s.size()) i++; 
     58         m++,ed[m]=x;
     59     }
     60     for (int i=1;i<=m;i++) ed[i]++;
     61     scanf("%d",&price);
     62     for (int i=1;i<n;i++) 
     63         if (a[i+1]>=0) add(i,i+1,a[i+1]);
     64     for (int i=n;i>1;i--) 
     65         if (a[i-1]>=0) add(i,i-1,a[i-1]);
     66     for (int i=1;i<=m;i++) 
     67         if (a[ed[i]]!=-1) add(st[i],ed[i],price),flag[cnt]=1;   
     68 }
     69 void spfa()
     70 {
     71     memset(dis,100,sizeof(dis));
     72     dis[1][0]=0,stack[1][0]=1;
     73      
     74     int hd=0,tl=1;
     75     p.push(make_pair(1,0));
     76     while (!p.empty())
     77     {
     78         fzy now=p.front();
     79         p.pop();
     80         int u=now.first,t=now.second;
     81         for (int i=head[u];i!=-1;i=next[i])
     82         {       
     83             int v=rea[i];
     84             if (flag[i])
     85             {
     86                 if (dis[v][t+1]>dis[u][t]+val[i]+t&&t<m)
     87                 {
     88                     dis[v][t+1]=dis[u][t]+val[i]+t;
     89                     skp[v][t+1]=skp[u][t]+1;
     90                     if (!stack[v][t+1])
     91                     {
     92                         stack[v][t+1]=1;
     93                         p.push(make_pair(v,t+1));
     94                     }
     95                 }
     96                 else if (dis[v][t+1]==dis[u][t]+val[i]+t) skp[v][t+1]=min(skp[v][t+1],skp[u][t]+1);
     97             }
     98             else if (dis[v][t]>dis[u][t]+val[i])
     99                  {
    100                      dis[v][t]=dis[u][t]+val[i];
    101                      skp[v][t]=skp[u][t]+1;
    102                      if (!stack[v][t])
    103                      {
    104                          stack[v][t]=1;
    105                          p.push(make_pair(v,t));                    
    106                      }
    107                  }
    108                  else if (dis[v][t]==dis[u][t]+val[i]) skp[v][t]=min(skp[v][t],skp[u][t]+1);
    109         }
    110         stack[u][t]=0;
    111     }
    112 }
    113 int main()
    114 {
    115     init();
    116     spfa();
    117      
    118     int ans1=INF,ans2=INF;
    119     for (int i=0;i<=m;i++)
    120         if (dis[n][i]<ans1) ans1=dis[n][i],ans2=skp[n][i];
    121         else if (dis[n][i]==ans1) ans2=min(ans2,skp[n][i]);
    122     if (ans1==INF) printf("-1 -1
    ");
    123     else printf("%d %d
    ",ans1,ans2-1);
    124 }
  • 相关阅读:
    Windows8.1 + Nvidia cuda8.0 + Vs2015
    读《鲜花帝国》有感
    oracle-sql书写
    oracle--聚合函数和case when结合使用
    oracle正则表达式
    oracle中case when使用
    oracle分区表之列表分区
    linux下oracl字符集修改(WE8ISO8859P1 --> ZHS16GBK)
    linux 下安装oracle数据库
    oracle学习笔记
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7210555.html
Copyright © 2011-2022 走看看