• P1082丛林探险


    P1082丛林探险

    描述

    东非大裂谷中有一片神秘的丛林,是全世界探险家的乐园,著名黄皮肤探险家BB一直想去试试。正好我国科学家2005年4月将首次对东非大裂谷进行科考,BB决定随科考队去神秘丛林探险。在出发之前,他搜集了国内外有关神秘丛林探险的资料,并绘制成一张地图:该地图上有若干安全点(包括入口点和出口点),并将这些安全点编号为1、2、…、n;如果一个安全点和另一个安全点有一条路直接相通,则用一条边标示;该图是一个连通图(任意两点间有至少一条路径),地图上每条路的长度和走这条路需要耗费的体力都做了标示。

    KK行走速度为1,并知道自己体力为K。他想知道根据自己的体力情况能否成功地穿过丛林。

    格式

    输入格式

    第一行两个整数n(<=5000) m(<=40000),分别表示地图上安全点的个数和边的数目;
    第2行至第m+1 行每行4个整数x y c d,x、y表示有直接相联边的两个点的编号,c走这条路需要耗费的体力;d表示边的长度;(其中150<=c,d<=300)
    第m+2行两个整数s t,分别表示安全的入口点和出口点的编号;
    第m+3行一个整数k,表示BB的体力值;(K<10^9)
    同一行上的多个数据用空格隔开。

    输出格式

    一个整数,如果BB能安全地从如入口穿过丛林到达出口,输出最短时间,否则输出-1

    样例1

    样例输入1

    4 5
    1 2 2 3
    1 3 3 5
    1 4 7 10
    2 4 4 6
    3 4 2 6
    1 4
    5

    样例输出1

    11

    限制

    各个测试点1s

    【思路】

      搜索+剪枝。

      n+m=45000,可以考虑搜索st之间的每一条路径,选择最短的一条。

      剪枝:

         最优性剪枝:如果dist>ans则剪枝。

         可行性剪枝:[最短路]预处理出点u到t的最小体力耗费d[u],如果Blood<d[u]则剪枝。

      需要注意的是方案的不可行最好在枚举v的时候判断,否则的话:我试了一下,一个TLE一个WA。(这个WA也是很奇妙的=-=)

    【代码】

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 using namespace std;
     5 
     6 const int maxn = 5000+10 , maxm=40000+10;
     7 const int INF=1<<30;
     8 struct Edge{
     9     int v,c,d,next;
    10 }e[2*maxm];
    11 int en=-1, front[maxn];
    12 
    13 int n,m,K;
    14 
    15 inline void AddEdge(int u,int v,int c,int d) {
    16     en++; e[en].v=v; e[en].c=c; e[en].d=d; e[en].next=front[u]; front[u]=en;
    17 }
    18 int d[maxn];
    19 void SPFA(int s) {
    20     int inq[maxn];
    21     queue<int> q;
    22     memset(inq,0,sizeof(inq));
    23     for(int i=1;i<=n;i++) d[i]=INF;
    24     
    25     d[s]=0; inq[s]=1; q.push(s);
    26     while(!q.empty()) {
    27         int u=q.front(); q.pop(); inq[u]=0;
    28         for(int i=front[u];i>=0;i=e[i].next) {
    29             int v=e[i].v,w=e[i].c;
    30             if(d[v]>d[u]+w) {
    31                 d[v]=d[u]+w;
    32                 if(!inq[v]) {
    33                     inq[v]=1;
    34                     q.push(v);
    35                 }
    36             }
    37         }
    38     }
    39 }
    40 
    41 int ans=INF;
    42 int vis[maxn];
    43 int s,t;
    44 void dfs(int u,int Blood,int dist) {
    45     if(u==t) { ans=dist; return; }
    46     for(int i=front[u];i>=0;i=e[i].next){
    47         int v=e[i].v;
    48         if(vis[v]) continue;
    49         if(dist+e[i].d>=ans || Blood-e[i].c<d[v]) continue;
    50         vis[v]=1;
    51         dfs(v,Blood-e[i].c,dist+e[i].d);
    52         vis[v]=0;
    53     }
    54 }
    55 int main() {
    56     memset(front,-1,sizeof(front));
    57     scanf("%d%d",&n,&m);
    58     int u,v,c,f;
    59     for(int i=0;i<m;i++) {
    60         scanf("%d%d%d%d",&u,&v,&c,&f);
    61         AddEdge(u,v,c,f);
    62         AddEdge(v,u,c,f);
    63     }
    64     scanf("%d%d%d",&s,&t,&K);
    65     SPFA(t);
    66     if(d[s]>K) printf("-1
    ");
    67     else 
    68     {
    69        vis[s]=1;
    70        dfs(s,K,0);
    71        vis[s]=0;
    72        printf("%d
    ",ans);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    MySql存储过程学习总结
    JAVA设计模式之策略模式
    JAVA设计模式之装饰模式
    JAVA设计模式之代理模式
    动手学servlet(四) cookie和session
    动手学servlet(三) 请求头和响应头信息
    动手学servlet(二) servlet基础
    动手学servlet(一) 第一个servlet程序
    HTTP与HttpServlet
    HttpServlet详解
  • 原文地址:https://www.cnblogs.com/lidaxin/p/4911740.html
Copyright © 2020-2023  润新知