201712-4行车路线

 

一、问题描述

试题编号:201712-4
试题名称:行车路线
时间限制:1.0s
内存限制:256.0MB
问题描述:

问题描述

  小明和小芳出去乡村玩,小明负责开车,小芳来导航。
  小芳将可能的道路分为大道和小道。大道比较好走,每走1公里小明会增加1的疲劳度。小道不好走,如果连续走小道,小明的疲劳值会快速增加,连续走s公里小明会增加s2的疲劳度。
  例如:有5个路口,1号路口到2号路口为小道,2号路口到3号路口为小道,3号路口到4号路口为大道,4号路口到5号路口为小道,相邻路口之间的距离都是2公里。如果小明从1号路口到5号路口,则总疲劳值为(2+2)2+2+22=16+2+4=22。
  现在小芳拿到了地图,请帮助她规划一个开车的路线,使得按这个路线开车小明的疲劳度最小。

输入格式

  输入的第一行包含两个整数nm,分别表示路口的数量和道路的数量。路口由1至n编号,小明需要开车从1号路口到n号路口。
  接下来m行描述道路,每行包含四个整数tabc,表示一条类型为t,连接ab两个路口,长度为c公里的双向道路。其中t为0表示大道,t为1表示小道。保证1号路口和n号路口是连通的。

输出格式

  输出一个整数,表示最优路线下小明的疲劳度。

样例输入

6 7
1 1 2 3
1 2 3 2
0 1 3 30
0 3 4 20
0 4 5 30
1 3 5 6
1 5 6 1

样例输出

76

样例说明

  从1走小道到2,再走小道到3,疲劳度为52=25;然后从3走大道经过4到达5,疲劳度为20+30=50;最后从5走小道到6,疲劳度为1。总共为76。

数据规模和约定

  对于30%的评测用例,1 ≤ n ≤ 8,1 ≤ m ≤ 10;
  对于另外20%的评测用例,不存在小道;
  对于另外20%的评测用例,所有的小道不相交;
  对于所有评测用例,1 ≤ n ≤ 500,1 ≤ m ≤ 105,1 ≤ ab ≤ nt是0或1,c ≤ 105。保证答案不超过106。

二、分析解答

说一说吧,其实一开始我就做对了,不过时间复杂度比较高,然后就瞎改,80分是因为我的那个算长度是一个函数特别复杂,然后好像是递归的,反正很慢。中间错了一堆是因为,我想把三个版本的函数几乎两两结合看看是哪里错了,然后就发现了一些我也不清楚的东西,总之乱改一通,其实都什么都没用。

没办法这题我干不动。只有90分,剩下的应该是超时,不会nlogn的代码。这是版本三。看着办吧,我好差劲一点也不会。

#include <iostream>
#include <climits>
#include <queue>
using namespace std;
#define INF LONG_LONG_MAX
#define MAX_NODE 505
#define BG 0
#define SM 1
#define NONE 2
///node,edge
int n_node,m_edge;
///edge
int t_type,a_start,b_end;
long long c_len;
///road
long long len[MAX_NODE][MAX_NODE];
int type[MAX_NODE][MAX_NODE];
int path[MAX_NODE];
long long tired[MAX_NODE];
long long before_sm[MAX_NODE];
long long last_sm[MAX_NODE];
void init_path_dist(int i){
    if(type[0][i]!=NONE){
        path[i]=0;
        tired[i]=(type[0][i] == BG ? len[0][i] : len[0][i]*len[0][i]);
        before_sm[i]=(type[0][i] == BG ? len[0][i] : 0);
        last_sm[i]=(type[0][i] == BG ? 0 : len[0][i]);
    }else{
        path[i]=-1;tired[i]=INF;
    }
}
long long dij(){
    priority_queue<node> que;
    ///put 0 in the the set
    int i,j;
    int flag[n_node]={};
    for(i=0;i<n_node;i++){
        init_path_dist(i);
    }
    flag[0]=1;
    ///put n-1 node in the set
    for(i=0;i<n_node-1;i++){
        ///explore: find mindist node from not in and make it in.
        long long mindist=INF,minindex=-1;
        for(j=0;j<n_node;j++){
            if(flag[j]==0&&tired[j]<mindist){
                minindex=j;mindist=tired[j];
            }
        }
        if(mindist>=INF)break;
        flag[minindex]=1;
        ///exploit:will the node reduce the dist?
        for(j=0;j<n_node;j++){
            if(flag[j]==0&&type[minindex][j]!=NONE){
                long long newdist=INF,t_last_sm=0,t_before=before_sm[minindex];
                if(type[minindex][j]==BG){
                    newdist=tired[minindex]+len[minindex][j];
                    t_before=newdist;
                }else if(type[minindex][j]==SM){
                    newdist=before_sm[minindex]+(last_sm[minindex]+len[minindex][j])*(last_sm[minindex]+len[minindex][j]);
                    t_last_sm=last_sm[minindex]+len[minindex][j];
                }
                ///cout<<minindex+1<<" "<<j+1<<" "<<" before:"<<before_sm[minindex]<<" last:"<<last_sm[j]<<" len:"<<len[minindex][j]<<" "<<newdist<<" "<<tired[j]<<endl;
                if(newdist<tired[j]){
                    path[j]=minindex;
                    tired[j]=newdist;
                    before_sm[j]=t_before;
                    last_sm[j]=t_last_sm;
                }
            }
        }
        //for(j=0;j<n_node;j++){
        //cout<<path[j]<<" ";
        //}cout<<endl;
    }
    return tired[n_node-1];
}
int main()
{
    ///input
    cin>>n_node>>m_edge;
    ///init
    int i,j;
    for(i=0;i<n_node;i++){
        for(j=0;j<n_node;j++){
            if(i==j){len[i][j]=0;type[i][j]=BG;}
            else{len[i][j]=INF;type[i][j]=NONE;}
        }
    }
    ///input
    for(i=0;i<m_edge;i++){
        cin>>t_type>>a_start>>b_end>>c_len;a_start--;b_end--;
        len[a_start][b_end]=len[b_end][a_start]=c_len;
        type[a_start][b_end]=type[b_end][a_start]=t_type;
    }
    cout << dij();
    return 0;
}

 

这也是我的90分代码,版本二。

#include <cstdio>
#include <iostream>
#include <climits>
using namespace std;
#define INF LONG_LONG_MAX
#define BG 0
#define SM 1
#define NONE 2
#define MAX_NODE 505
#define MAX_EDGE 100005
///node,edge
int n_node,m_edge;
///edge
int t_type,a_start,b_end;
long long c_len;
///road
typedef struct ROAD{
    long long len[MAX_NODE][MAX_NODE];
    int type[MAX_NODE][MAX_NODE];
    int path[MAX_NODE];
    long long tir[MAX_NODE];
    long long l_sm[MAX_NODE];
}Road;
Road road;
///end!=0
long long dist(int end){
    ///not connect
    if(road.path[end]==-1){
        return INF;
    }
    int i,j;
    int last_type=NONE;
    long long sum=0,tmp=0;
    for(i=end;i!=0;i=j){
        j=road.path[i];
        if(last_type==NONE){
            tmp=road.len[j][i];
            last_type=road.type[j][i];
            continue;
        }
        if(road.type[j][i]!=last_type){
            if(last_type==BG){
                sum+=tmp;
            }else if(last_type==SM){
                sum+=(tmp*tmp);
            }
            last_type=road.type[j][i];
            tmp=road.len[j][i];
        }else{
            last_type=road.type[j][i];
            tmp+=road.len[j][i];
        }
    }
    if(last_type==BG){
        sum+=tmp;
    }else if(last_type==SM){
        sum+=(tmp*tmp);
    }
    return sum;
}
///mid!=0
long long dist_mid(int mid,int next){
    long long lenn=0;
    int tmp=road.path[next];
    road.path[next]=mid;
    lenn=dist(next);
    road.path[next]=tmp;
    return lenn;
}
///0->n-1
long long dij(){
    ///init
    int i,j;
    for(i=0;i<n_node;i++){
        if(road.len[0][i]<INF){
            road.path[i]=0;
        }else{
            road.path[i]=-1;
        }
    }
    ///put in n node
    int flag[n_node]={};
    flag[0]=1;
    for(i=0;i<n_node-1;i++){
        ///find mindist from not in and make it in.explore!
        long long mindist=INF,minindex=-1;
        for(j=0;j<n_node;j++){
            if(flag[j]==0&&dist(j)<mindist){
                minindex=j;mindist=dist(j);
            }
        }
        if(mindist>=INF)break;
        flag[minindex]=1;
        ///is there some change?exploit!
        for(j=0;j<n_node;j++){
            if(flag[j]==0&&road.len[minindex][j]!=INF&&dist_mid(minindex,j)<dist(j)){
                road.path[j]=minindex;
            }
        }
    }
    return dist(n_node-1);
}

int main(){
    ///input
    cin>>n_node>>m_edge;
    ///init
    int i,j;
    for(i=0;i<n_node;i++){
        for(j=0;j<n_node;j++){
            if(i==j){
                road.len[i][j]=0;
                road.type[i][j]=NONE;
            }else{
                road.len[i][j]=INF;
                road.type[i][j]=NONE;
            }
        }
    }
    ///input
    for(i=0;i<m_edge;i++){
        cin>>t_type>>a_start>>b_end>>c_len;
        a_start--;b_end--;
        road.len[a_start][b_end]=road.len[b_end][a_start]=c_len;
        road.type[a_start][b_end]=road.type[b_end][a_start]=t_type;
    }
    long long tired = dij();
    cout << tired;
    return 0;
}

还有这个,是版本一,也是90分。

#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
#define INF 0x3f3f3f3f
#define BG 0
#define SM 1
#define MAX_NODE 505
#define MAX_EDGE 100000
///node,edge,
int n_node,m_edge;
///edge
long long t_type,a_start,b_end,c_len;
///road
typedef struct ROAD{
    long long len[MAX_NODE][MAX_NODE];
    int type[MAX_NODE][MAX_NODE];
    int path[MAX_NODE];
}Road;

Road road;

long long dist(int end){
    if(road.path[end]==-1){
        return INF;
    }
    int i,j;
    int last_type=-1;
    long long sum=0,tmp=0;
    for(i=end;i!=0;i=j){
        j=road.path[i];
        if(road.type[j][i]!=last_type){
            if(last_type==BG){
                sum+=tmp;
            }else if(last_type==SM){
                sum+=(tmp*tmp);
            }else{
                tmp=road.len[j][i];
                last_type=road.type[j][i];
                continue;
            }
            tmp=0;
        }
        last_type=road.type[j][i];
        tmp+=road.len[j][i];
    }
    if(last_type==BG){
        sum+=tmp;
    }else if(last_type==SM){
        sum+=(tmp*tmp);
    }
    //cout<<sum;
    return sum;
}
long long dist_mid(int mid,int next){
    if(road.len[mid][next]==INF){
        return INF;
    }
    int x=road.path[mid];
    long long lenn=0;
    if(road.type[mid][next]==road.type[x][mid]){
        int m=road.path[next];
        road.path[next]=mid;
        lenn=dist(next);
        road.path[next]=m;
    }else{
        lenn=dist(mid)+road.len[mid][next];
    }
    return lenn;
}

///0->n-1
long long dij(){
    int i,j;
    for(i=0;i<n_node;i++){
        if(road.len[0][i]<INF)
            road.path[i]=0;
        else
            road.path[i]=-1;
    }
    ///put in n node
    int flag[n_node]={};
    flag[0]=1;
    for(i=0;i<n_node-1;i++){
        ///find mindist from not in and make it in.explore!
        long long mindist=INF,minindex=-1;
        for(j=0;j<n_node;j++){
            if(flag[j]==0&&dist(j)<mindist){
                minindex=j;mindist=dist(j);
            }
        }
        ///cout<<minindex<<" "<<mindist<<endl;
        flag[minindex]=1;
        ///is there some change?exploit!
        for(j=0;j<n_node;j++){
            if(mindist!=INF&&flag[j]==0&&dist_mid(minindex,j)<dist(j)){
                road.path[j]=minindex;
            }
        }
    }
//    for(i=0;i<n_node;i++){
//        cout<<road.path[i]<<" "<<dist(i)<<endl;
//    }
    return dist(n_node-1);
}

int main(){
    ///input
    cin>>n_node>>m_edge;
    int i,j;
    for(i=0;i<n_node;i++){
        for(j=0;j<n_node;j++){
            if(i==j){
                road.len[i][j]=0;
                road.type[i][j]=0;
            }else{
                road.len[i][j]=INF;
                road.type[i][j]=-2;
            }
        }
    }
    for(i=0;i<m_edge;i++){
        cin>>t_type>>a_start>>b_end>>c_len;a_start--;b_end--;
        road.len[a_start][b_end]=road.len[b_end][a_start]=c_len;
        road.type[a_start][b_end]=road.type[b_end][a_start]=t_type;
    }
    long long tired = dij();
    cout << tired;
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值