【BZOJ3627】【JLOI2014】路径规划 分层图

题意:自己看,这有传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3627

注意:点的等待时长示意图为:

很清晰了吧?没事,不清晰就不清晰吧,反正公式给你了,这不是本题知识点,扒就行了。

题解:

看到这题的数据范围,我们就想到了分层图,可是现在有两种需要分层的东西:剩余油量的限制,和经过红绿灯的限制。所以我们要搞掉其中一个,使题目转化成分层图。红绿灯限制很不好惹的样子,所以我们还是把剩余油量的限制搞掉吧。

怎么搞掉油量的限制呢?我们可以把整个图缩成一个只有加油站的图,这样两加油站之间只要可以直接到达,就不用再管【剩余油量】了!当然,起点和终点也要算到加油站中,至于终点可能多加的一份【加油费用】,再删掉就好了~

具体做法:很简单地说。。枚举每个加油站,看满油从它出发能跑到哪些点,然后建边(新图的边,点为加油站的图的边),而两点之间根据经过红绿灯的不同,所以可能有多条边。。再简单一点的说法就是——看下述代码!!

好了,新图建好了,跑一遍水水的分层图吧。就是dist[i][j]表示到j时经过i个红绿灯的最短路径,至于若j有红灯时算不算上神马的就不用写得太拘束了,爱怎么写怎么写,题目到这里已经很水了。。

注意:

我们在预处理节点名称的时候不妨建一棵字典树,这样找起来会很快,代码也很好写。不然可能就需要写一发pq优化的nlogn最短路,哪个好写,自己想吧。另,如果想刷rank,这两个都得写!!!

如果不会分层图的话,不妨看看这一篇:http://blog.csdn.net/vmurder/article/details/40075989

好了,直接贴代码,写得比较清晰,只是因为代码量的缘故才会看着发晕。认真仔细一点很容易看懂(大不了你用样例数据手调一下我的代码!不信看不懂!)

(原题数据范围错了,n和m都应该是原来的2倍。)

/**************************************************************
    Problem: 3627
    User: 18357
    Language: C++
    Result: Accepted
    Time:716 ms
    Memory:69628 kb
****************************************************************/

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 10100
#define M 20100
#define P 60
#define TT 80
#define eps 1e-7
#define inf 0x3f3f3f3f
using namespace std;
/*i won't tell you it's a trie. */
struct Trie
{
    int next[N*20][TT],cnt;
    int note[N*20],sign;
    char s[TT];
    inline int insert()
    {
        scanf("%s",s+1);
        int x=0,i,alp;
        for(i=1;s[i];i++)
        {
            alp=s[i]-'0';
            if(!next[x][alp])next[x][alp]=++cnt;
            x=next[x][alp];
        }
        if(!note[x])note[x]=++sign;
        return note[x];
    }
    inline int judge()
    {
        for(int i=1;s[i];i++)if(i>=5&&s[i]=='t'&&s[i-1]=='r'&&s[i-2]=='a'&&s[i-3]=='t'&&s[i-4]=='s')return 1;
        for(int i=1;s[i];i++)if(i>=3&&s[i]=='s'&&s[i-1]=='a'&&s[i-2]=='g')return 2;
        for(int i=1;s[i];i++)if(i>=3&&s[i]=='d'&&s[i-1]=='n'&&s[i-2]=='e')return 3;
        return 0;
    }
}trie;
/*for original graph or prespfa or the gas_station graph. */
struct KSD
{
    int u,v,next;
    double len;
}e[M<<1],E[15][P*P<<1];
int head[N],cnt;
void add(int u,int v,double len)
{
    cnt++;
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].len=len;
    e[cnt].next=head[u];
    head[u]=cnt;
}
int HEAD[15][P],CNT[15];
void ADD(int light,int u,int v,double len)
{/*i feel sick for my code here, but i can't do anything. */
    CNT[light]++;
    E[light][CNT[light]].u=u;
    E[light][CNT[light]].v=v;
    E[light][CNT[light]].len=len;
    E[light][CNT[light]].next=HEAD[light][u];
    HEAD[light][u]=CNT[light];
}
struct Lux
{
    int x,y;
    Lux(int _x,int _y):x(_x),y(_y){}
    Lux(){}
};
queue<Lux>q;
double dist[15][N];
bool in[15][N];
/*for static code*/
int n,m,lig,gas,cost;
/*for each point*/
bool red[N];
int sta[N];
double ave[N];
int gas_station[N],num;
/*for temp input*/
char ttt[TT];

void prespfa(int S)
{/*build the direct combinations between the gas_stations. */
    while(!q.empty())q.pop();
    memset(dist,0x7f,sizeof(dist));
    int i,v,temp;
    dist[0][S]=0;
    in[0][S]=1;
    q.push(Lux(0,S));
    while(!q.empty())
    {
        Lux U=q.front();q.pop();in[U.x][U.y]=0;
        for(i=head[U.y];i;i=e[i].next)
        {
            v=e[i].v;
            temp=U.x+red[v];
            if(temp<=lig&&dist[U.x][U.y]+e[i].len+ave[v]<=gas&&dist[temp][v]>dist[U.x][U.y]+e[i].len+ave[v])
            {
                dist[temp][v]=dist[U.x][U.y]+e[i].len+ave[v];
                if(!in[temp][v])in[temp][v]=1,q.push(Lux(temp,v));
            }
        }
    }
}
double divspfa(int S,int T)
{
    while(!q.empty())q.pop();
    memset(dist,0x7f,sizeof(dist));
    int i,j,v,temp;
    dist[0][S]=0;
    in[0][S]=1;
    q.push(Lux(0,S));
    while(!q.empty())
    {
        Lux U=q.front();q.pop();in[U.x][U.y]=0;
        for(j=0;j+U.x<=lig;j++)
        {
            for(i=HEAD[j][U.y];i;i=E[j][i].next)
            {
                v=E[j][i].v;
                if(dist[j+U.x][v]>dist[U.x][U.y]+E[j][i].len+cost)
                {
                    dist[j+U.x][v]=dist[U.x][U.y]+E[j][i].len+cost;
                    if(!in[j+U.x][v])in[j+U.x][v]=1,q.push(Lux(j+U.x,v));
                }
            }
        }
    }
    double ret=99999999999.999;
    for(i=0;i<=lig;i++)ret=min(ret,dist[i][T]);
    return ret;
}

void work()
{
    int i,j,k;
    double a,b,c;
    int ia,ib;
    int s,t,v;
    /*i just think it's not
        [graceful]
    to input in the main function. */
    scanf("%d%d%d%d%d",&n,&m,&lig,&gas,&cost);
    for(i=1;i<=n;i++)
    {
        trie.insert();
        if(k=trie.judge())
        {
            sta[i]=++num;
            gas_station[num]=i;
            if(k==1)s=i;
            if(k==3)t=i;
        }
        scanf("%lf%lf",&a,&b);
        if(k==1||k==3)continue;
        if(a>eps)
            red[i]=1,ave[i]=a*a/2.0/(a+b);
    }
    for(i=1;i<=m;i++)
    {
        ia=trie.insert();
        ib=trie.insert();
        scanf("%s",ttt);
        scanf("%lf",&c);
        add(ia,ib,c);
        add(ib,ia,c);
    }

    for(i=1;i<=num;i++)
    {
        prespfa(gas_station[i]);
        for(j=1;j<=num;j++)
        {
            v=gas_station[j];
            if(j!=i)
            {
                for(k=0;k<=lig;k++)
                {
                    if(dist[k][v]<inf)
                    {
                        ADD(k,i,j,dist[k][v]);
                    }
                }
            }
        }
    }
    printf("%.3lf\n",divspfa(sta[s],sta[t])-cost);
}

int main()
{
//  freopen("pathplan.in","r",stdin);
//  freopen("pathplan.out","w",stdout);
//  freopen("test.in","r",stdin);
    work();
    return 0;
}
时间: 2024-08-02 19:35:52

【BZOJ3627】【JLOI2014】路径规划 分层图的相关文章

【BZOJ-3627】路径规划 分层图 + Dijkstra + spfa

3627: [JLOI2014]路径规划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 186  Solved: 70[Submit][Status][Discuss] Description 相信大家都用过地图上的路径规划功能,只要输入起点终点就能找出一条最优路线.现在告诉你一张地图的信息,请你找出最优路径(即最短路径).考虑到实际情况,一辆车加满油能开的时间有限,所以在地图上增加了几个加油站. 地图由点和双向边构成,每个点代表一个路口,也有可

BZOJ 3627 JLOI2014 路径规划 分层图+堆优化SPFA JLOI2014全AC达成!

题目大意:给定一个无向图,每条边有边权,有些点有点权,一些点是加油站,求一条起点到终点的最短路,使经过有点权的点不超过k次,一管油只能走limit的时间,时间到了就只能到加油站花cost的时间加油 那个红绿灯的计算公式是 red*red/2/(red+green) 考场上很多人没推出来这个挂掉了 我推出来不会写,写了爆搜,26分 限制条件有点多...考虑到k<=10,加油站<=50,我们可以对k进行分层处理,将图缩点,转化成一个在加油站之间行走的图,这样k和limit的限制条件就都解除了 首先

BZOJ3627 [JLOI2014]路径规划

题意:求期望红绿灯时间下.途径若干加油站.经过最多若干个红绿灯,起点与终点的最短路. 思路:每一个有红绿灯的节点通过时间怎么算呢?其实t=red*red/2/(red+green),然后把这个时间附加到节点的出边上. 随后我们建立分层图,第i层表示经过了i个红绿灯时,从源点到该点的最短路径长度. 假设没有油量限制.那么我们直接跑最短路即可了. 注意到加油站非常少,于是我们枚举以每一个加油站为起点,向其它加油站经过若干个红绿灯的最短路径. 若此长度不大于最大油量,那么能够直接转移. 我们用上述信息

BZOJ 3627 JLOI 2014 路径规划 分层图 SPFA+HEAP

题目大意:N个点M条无向边,每个点有可能有红绿灯,或者是加油站,或者单单是一个点.红绿灯太多会让人烦,太久不加油车子就会开不动,问最多通过K次红绿灯,从"start"点到"end"点的最少花费是多少. 思路:只能最多通过K次红绿灯,可以依据这个建分层图.f[ i ][ j ]为在已经通过i次红绿灯后,在j点时的最小花费.这只是总体的思路,具体是实现起来还是有其他一些小问题. 题目中有一个limit,表示从一个加油站到另一个加油站不能行驶超过这么远.仔细想想,其实那些

BZOJ-3627路径规划分层图+Dijkstra+spfa2au

廈扇晾拷諏酝盖接叫淳布棺凡沽岸 洪灵枢只能硬着头皮与陆诩并肩而行逐渐与其他人拉开距离洪灵枢随后发现两人身后远 罾侗漭孀 陆丞燕翘了翘嘴角徐凤年笑着转身再转身果然看到她双指拧袖站在门口没有挪步朝 身份显赫的世子殿下.慕容桐皇还能坚持始终与徐凤年对视. 轧检ホ¢ 匦函挽 一名白袍男子从船舱中走出跟两人擦肩而过走到两鬓斑白的儒生附近低头瞥了一眼. 上回在龙晴郡鱼龙帮也露过面这次被调入陵州将军府徐凤年记得当时跟汪植要人的时候 亲卫没有转身只是突然嘶吼道:"不带!老子就带两分银子一壶的破酒给你们到时候将

基于分层路网的路径规划算法

http://www.docin.com/p-1308678703.html 路径规划一般包括如下几种情况: 最短路径规划 最短时间规划 最经济规划 通过赋予图中的边以不同的权值来满足用户不同的需求 最短路径由于普通道路限速问题,未必是最短时间到达目的地, 可能上高速更快一些 分层思想 对于一个点P,以自身为中心,不断的扩大半径进行搜索,查看当前是否包括一个升级到高层路网的节点 如果有,说明当设置P为起点,然后设置T为终点,而且当distance(pt)> R,说明应该进行路网的升层 选择一个查

iOS百度地图路径规划和POI检索详细总结-b

路径规划.png 百度地图的使用 百度地图API的导入网上说了许多坑,不过我遇到的比较少,这里就放两个比较常见的吧.坑一: 奥联WIFI_xcodeproj.png 如上图所示,在infoplist里加入这个字段,而且这里还可以设置提示的内容.不加的话,嘿嘿嘿,期待你的尝试.坑二:如下图 Pasted_Graphic_jpg.png 导入百度地图API运行之后报上图错误大约18到20个左右,解决方法添加libstdc++.6.0.9 的库.填完坑之后看一下我们今天要演示的效果吧. 路线规划图.g

路径规划

机器人路径规划研究综述 1.什么是路径规划 路径规划技术是机器人研究领域中的一个重要分支.所谓机器人的最优路径规划问题,就是依据某个或某些优化准则(如工作代价最小,行走路线最短,行走时间最短等),在其工作空间中找到一条从起始状态到目标状态的能避开障碍物的最优路径. 依据某种最优准则,在工作空间中寻找一条从起始状态到目标状态的避开障碍物的最优路径. 需要解决的问题: 1.始于初始点止于目标点. 2.避障. 3.尽可能优化的路径. 2.路径规划技术分类 a.静态结构化环境下的路径规划,比如说slam

PRM路径规划算法

路径规划作为机器人完成各种任务的基础,一直是研究的热点.研究人员提出了许多规划方法:如人工势场法.单元分解法.随机路标图(PRM)法.快速搜索树(RRT)法等.传统的人工势场.单元分解法需要对空间中的障碍物进行精确建模,当环境中的障碍物较为复杂时,将导致规划算法计算量较大.基于随机采样技术的PRM法可以有效解决高维空间和复杂约束中的路径规划问题. PRM是一种基于图搜索的方法,它将连续空间转换成离散空间,再利用A*等搜索算法在路线图上寻找路径,以提高搜索效率.这种方法能用相对少的随机采样点来找到