【搜索】丛林探险

来源:互联网 发布:2014网络十大神曲 编辑:程序博客网 时间:2024/04/28 02:29
描述 Description  东非大裂谷中有一片神秘的丛林,是全世界探险家的乐园,著名黄皮肤探险家BB一直想去试试。正好我国科学家2005年4月将首次对东非大裂谷进行科考,BB决定随科考队去神秘丛林探险。在出发之前,他搜集了国内外有关神秘丛林探险的资料,并绘制成一张地图:该地图上有若干安全点(包括入口点和出口点),并将这些安全点编号为1、2、…、n;如果一个安全点和另一个安全点有一条路直接相通,则用一条边标示;该图是一个连通图(任意两点间有至少一条路径),地图上每条路的长度和走这条路需要耗费的体力都做了标示。
KK行走速度为1,并知道自己体力为K。他想知道根据自己的体力情况能否成功地穿过丛林。       输入格式 Input Format  第一行两个整数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)
同一行上的多个数据用空格隔开。       输出格式 Output Format  一个整数,如果BB能安全地从如入口穿过丛林到达出口,输出最短时间,否则输出-1       样例输入 Sample Input         样例输出 Sample Output         时间限制 Time Limitation  各个测试点1s


有人用最短路做出来了,应该是数据弱了的原因。他们的方法是比较的时候先比较长度,再比较体力,实际上有反例。

因为一开始体力没超过限制的时候,就会尽量先满足长度最短而使体力变大,可能导致最后体力超过限制。实际上一开始为了保证能到达,不一定选择路径最短。


搜索是可以的,加个最优化剪枝就能过。


#include <cstdio>#include <algorithm>#include <string>#include <cstring>using std::sort;long s,t,k;long ans = 0x3f3f3f3f;long long dist[5010];bool used[5010];long que[2000010];const long qmod = 2000000;/*struct node{long ind;long strenth;long length;node* nxt;};node* head[5010];*/struct Edge{long u;long v;long strenth;long length;bool operator<(const Edge& e2)const{return u < e2.u;}};Edge edge[80010];long start[5010];long getint(){long rs=0;bool sgn=1;char tmp;do tmp = getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp == '-'){tmp=getchar();sgn=0;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;}void spfa1(){memset(dist,0x3f,sizeof dist);dist[s] = 0;long l = 0;long r = 0;que[++r] = s;long u ,v;while (l < r){l ++;if (l == qmod)l = 0;u = que[l];used[u] = false;for (long vv=start[u];edge[vv].u==u;vv++){v = edge[vv].v;if (dist[v]>dist[u]+edge[vv].strenth){dist[v] = dist[u] + edge[vv].strenth;if (!used[v]){used[v] = true;r ++;if (r == qmod)r = 0;que[r] = v;}}}}}void dfs(long u,long ss,long sl){if (sl >= ans){return;}if (u == t){if (ans > sl)ans = sl;return;}for (long vv=start[u];edge[vv].u==u;vv++){long v = edge[vv].v;if (!used[v] && ss+edge[vv].strenth<=k){used[v] = true;dfs(v,ss+edge[vv].strenth,sl+edge[vv].length);used[v] = false;}}}/*void insert(long a,long b,long c,long d){node* nn = new node;nn -> ind = b;nn -> nxt = head[a];nn -> strenth = c;nn -> length = d;head[a] = nn;nn = new node;nn -> ind = a;nn -> nxt = head[b];nn -> strenth = c;nn -> length = d;head[b] = nn;}*/int main(){freopen("forest.in","r",stdin);freopen("forest.out","w",stdout);long n = getint();long m = getint();for (long i=0;i<m;i++){edge[i*2+1].u = edge[i*2+2].v = getint();edge[i*2+1].v = edge[i*2+2].u = getint();edge[i*2+1].strenth = edge[i*2+2].strenth = getint();edge[i*2+1].length = edge[i*2+2].length = getint();}m <<= 1;sort(edge+1,edge+m+1);for (long i=1;i<m+1;i++){if (!start[edge[i].u]){start[edge[i].u] = i;}}s = getint();t = getint();k = getint();spfa1();if (dist[t] > k){printf("-1");return 0;}used[s] = true;dfs(s,0,0);printf("%ld",ans);return 0;}


二分版本

#include <cstdio>#include <string>#include <cstring>long s,t,k;long n;long mid;bool used[5010];struct node{long ind;node* nxt;long c;long d;};node* head[5010];long getint(){long rs=0;bool sgn=1;char tmp;do tmp=getchar();while (!isdigit(tmp)&&tmp-'-');if (tmp=='-'){tmp=getchar();sgn=0;}do rs=(rs<<3)+(rs<<1)+tmp-'0';while (isdigit(tmp=getchar()));return sgn?rs:-rs;}void insert(long a,long b,long c,long d){node* nn = new node;nn -> ind = b;nn -> nxt = head[a];nn -> c = c;nn -> d = d;head[a] = nn;}bool can(long u,long e,long s){if (s > mid)return false;if (u == t){if (mid > s)mid = s;return true;}for (node* vv=head[u];vv;vv=vv->nxt){long v = vv->ind;if (!used[v]){if (e-vv->c >= 0){used[v] = true;if (can(v,e-vv->c,s+vv->d))return true;used[v] = false;}}}return false;}int main(){freopen("forest.in","r",stdin);freopen("forest.out","w",stdout);n = getint();long m = getint();long sumd = 0;for (long i=1;i<m+1;i++){long x = getint();long y = getint();long c = getint();long d = getint();insert(x,y,c,d);insert(y,x,c,d);sumd += d;}s = getint();t = getint();k = getint();long ans = 0x3f3f3f3f;long l = 0;long r = sumd;while (l <= r){mid = (l+r)>>1;memset(used,0,sizeof used);used[s] = true;if (can(s,k,0)){if (ans > mid)ans = mid;r = mid-1;}else{l = mid+1;}}if (ans == 0x3f3f3f3f)printf("-1");elseprintf("%ld",ans);return 0 ;}


原创粉丝点击