题意:
给你起点终点,和一些加油站,和每次加油后的最大行驶距离,问你从起点到终点最少加油次数,要求两点之间必须走直线,见到加油站必须加油,也就是说如果想从a走到b,那么a,b连线上的加油站必须加油。
思路:
关键就是处理a,b,之间的点必须加油这个问题,我们可以排序,x小的或者x相等y小的在前面,然后枚举每条边,对于每个点为起点的边如果当前的斜率出现过,那么我们就可以不加这条边(或者是在费用上增加1后加上这条边),不加的原因是我们可以再后面加,比如a -> b ->c 我们可以 a ->b ,然后b->c,(也可以a->c 距离+1),标记每一个点为起点的斜率,斜率出现过就不加了,标记斜率可以用容器,总的建图时间复杂度是
给你起点终点,和一些加油站,和每次加油后的最大行驶距离,问你从起点到终点最少加油次数,要求两点之间必须走直线,见到加油站必须加油,也就是说如果想从a走到b,那么a,b连线上的加油站必须加油。
思路:
关键就是处理a,b,之间的点必须加油这个问题,我们可以排序,x小的或者x相等y小的在前面,然后枚举每条边,对于每个点为起点的边如果当前的斜率出现过,那么我们就可以不加这条边(或者是在费用上增加1后加上这条边),不加的原因是我们可以再后面加,比如a -> b ->c 我们可以 a ->b ,然后b->c,(也可以a->c 距离+1),标记每一个点为起点的斜率,斜率出现过就不加了,标记斜率可以用容器,总的建图时间复杂度是
O(n*n*log(n)) log(n)是因为map操作需要一个log级的时间复杂度。
斜率相同直接跳过
#include<stdio.h> #include<string.h> #include<queue> #include<algorithm> #include<math.h> #include<map> #define N_node 1000 + 100 #define N_edge 1000000 + 1000 #define INF 0x3f3f3f3f using namespace std; typedef struct { int to ,next ,cost; }STAR; typedef struct { double x ,y; int id; }NODE; STAR E[N_edge]; NODE node[N_node]; int list[N_node] ,tot; int s_x[N_node]; map<double ,int>hash; void add(int a ,int b ,int c) { E[++tot].to = b; E[tot].cost = c; E[tot].next = list[a]; list[a] = tot; } double dis(NODE a ,NODE b) { double x = (a.x - b.x) * (a.x - b.x); double y = (a.y - b.y) * (a.y - b.y); return sqrt(x + y); } bool camp(NODE a ,NODE b) { return a.x < b.x || a.x == b.x && a.y < b.y; } void spfa(int s ,int n) { int mark[N_node] = {0}; for(int i = 0 ;i <= n ;i ++) s_x[i] = INF; queue<int>q; q.push(s); mark[s] = 1 ,s_x[s] = 0; while(!q.empty()) { int xin ,tou; tou = q.front(); q.pop(); mark[tou] = 0; for(int k = list[tou] ;k ;k = E[k].next) { int xin = E[k].to; if(s_x[xin] > s_x[tou] + E[k].cost) { s_x[xin] = s_x[tou] + E[k].cost; if(!mark[xin]) { mark[xin] = 1; q.push(xin); } } } } } int main () { int n ,i ,j ,t; double L; scanf("%d" ,&t); while(t--) { scanf("%d %lf" ,&n ,&L); scanf("%lf %lf" ,&node[1].x ,&node[1].y); scanf("%lf %lf" ,&node[2].x ,&node[2].y); node[1].id = 1 ,node[2].id = 2; for(n += 2 ,i = 3 ;i <= n ;i ++) { scanf("%lf %lf" ,&node[i].x ,&node[i].y); node[i].id = i; } sort(node + 1 ,node + n + 1 ,camp); for(i = 1 ;i <= n ;i ++) { hash.clear(); for(j = i + 1 ;j <= n ;j ++) if(dis(node[i] ,node[j]) <= L) { double xx = node[j].x - node[i].x; double yy = node[j].y - node[i].y; double v = xx == 0 ? -INF : yy / xx; if(hash[v]) continue; hash[v] = 1; add(node[i].id ,node[j].id ,hash[v]); add(node[j].id ,node[i].id ,hash[v]); } } spfa(1 ,n); int ans = s_x[2]; ans == INF ? puts("impossible") : printf("%d\n" ,ans - 1); } return 0; }
出现过的斜率那么就累加1的(跟上面的只有两行不同,其他的相同)
#include<stdio.h> #include<string.h> #include<queue> #include<algorithm> #include<math.h> #include<map> #define N_node 1000 + 100 #define N_edge 1000000 + 1000 #define INF 0x3f3f3f3f using namespace std; typedef struct { int to ,next ,cost; }STAR; typedef struct { double x ,y; int id; }NODE; STAR E[N_edge]; NODE node[N_node]; int list[N_node] ,tot; int s_x[N_node]; map<double ,int>hash; void add(int a ,int b ,int c) { E[++tot].to = b; E[tot].cost = c; E[tot].next = list[a]; list[a] = tot; } double dis(NODE a ,NODE b) { double x = (a.x - b.x) * (a.x - b.x); double y = (a.y - b.y) * (a.y - b.y); return sqrt(x + y); } bool camp(NODE a ,NODE b) { return a.x < b.x || a.x == b.x && a.y < b.y; } void spfa(int s ,int n) { int mark[N_node] = {0}; for(int i = 0 ;i <= n ;i ++) s_x[i] = INF; queue<int>q; q.push(s); mark[s] = 1 ,s_x[s] = 0; while(!q.empty()) { int xin ,tou; tou = q.front(); q.pop(); mark[tou] = 0; for(int k = list[tou] ;k ;k = E[k].next) { int xin = E[k].to; if(s_x[xin] > s_x[tou] + E[k].cost) { s_x[xin] = s_x[tou] + E[k].cost; if(!mark[xin]) { mark[xin] = 1; q.push(xin); } } } } } int main () { int n ,i ,j ,t; double L; scanf("%d" ,&t); while(t--) { scanf("%d %lf" ,&n ,&L); scanf("%lf %lf" ,&node[1].x ,&node[1].y); scanf("%lf %lf" ,&node[2].x ,&node[2].y); node[1].id = 1 ,node[2].id = 2; for(n += 2 ,i = 3 ;i <= n ;i ++) { scanf("%lf %lf" ,&node[i].x ,&node[i].y); node[i].id = i; } sort(node + 1 ,node + n + 1 ,camp); memset(list ,0 ,sizeof(list)) ,tot = 1; for(i = 1 ;i <= n ;i ++) { hash.clear(); for(j = i + 1 ;j <= n ;j ++) if(dis(node[i] ,node[j]) <= L) { double xx = node[j].x - node[i].x; double yy = node[j].y - node[i].y; double v = (xx == 0 ? -INF : yy / xx); //if(hash[v]) continue; hash[v] ++; add(node[i].id ,node[j].id ,hash[v]); add(node[j].id ,node[i].id ,hash[v]); } } spfa(1 ,n); int ans = s_x[2]; ans == INF ? puts("impossible") : printf("%d\n" ,ans - 1); } return 0; }