题目原文

问题描述题目链接登陆账号有问题,要从这个链接登陆,然后点击“模拟考试”,进去找本题目)
试题编号: 201403-4
试题名称: 无线网络
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  目前在一个很大的平面房间里有 n 个无线路由器,每个无线路由器都固定在某个点上。任何两个无线路由器只要距离不超过 r 就能互相建立网络连接。
  除此以外,另有 m 个可以摆放无线路由器的位置。你可以在这些位置中选择至多 k 个增设新的路由器。
  你的目标是使得第 1 个路由器和第 2 个路由器之间的网络连接经过尽量少的中转路由器。请问在最优方案下中转路由器的最少个数是多少?
 
输入格式
  第一行包含四个正整数 n,m,k,r。(2 ≤ n ≤ 100,1 ≤ k ≤ m ≤ 100, 1 ≤ r ≤ 108)。
  接下来 n 行,每行包含两个整数 xi 和 yi,表示一个已经放置好的无线 路由器在 (xi, yi) 点处。输入数据保证第 1 和第 2 个路由器在仅有这 n 个路由器的情况下已经可以互               相连接(经过一系列的中转路由器)。
  接下来 m 行,每行包含两个整数 xi 和 yi,表示 (xi, yi) 点处可以增设 一个路由器。
  输入中所有的坐标的绝对值不超过 108,保证输入中的坐标各不相同。
 
输出格式
  输出只有一个数,即在指定的位置中增设 k 个路由器后,从第 1 个路 由器到第 2 个路由器最少经过的中转路由器的个数。
 
样例输入
5 3 1 3
0 0
5 5
0 3
0 5
3 5
3 3
4 4
3 0
 
样例输出
2

题目大意

给你n个点,随后给出的每个点的坐标,再给你m个候选点,从m个候选点中选择最多k个点作为新增设的点。给定数值r作为一个点可到达另一个点的最远距离(可以等于)。现让你计算出从起始坐标(坐标点从0算起,第0个点为起始坐标)到终点坐标(第1个点)最少需要经历多少个点(可以有新增设的点,但不能超过k个)。

题目思路

权值均为1的SPFA。设置一个dec_[205][105]数组,dec_[i][k]表示经过了k个新增设的点到达第i个点最短距离是多少。采用SPFA思想(并不是BFS)。

举一组数据:(应该输出10)

10 4 2 1
0 0
5 0
0 1
0 2
0 3
1 3
3 0
3 1
3 2
3 3
1 0
2 0
2 3
4 0

仔细看一下数据和图解,绘制很辛苦,如果这个题思考很久没思路其他题解看不懂就用心看我这个,很详细。

前面和bfs一样,后面类似动态选择一样,这也是SPFA的特点,不是每个距离够的相邻点都能进入队列,成为下一个可走节点,而是还要判断是否需要松弛,松弛什么意思我也不懂,SPFA里,距离更近的赋值给我就说成是松弛。

对每一个dec_数组都设置成int最大数值,有现成函数INT_MAX。(这题可以这样写,但是一般不设置为INT_MAX,因为如果涉及到值为INT_MAX这个数据的变量,一旦加数字就会为负数,所以一般根据情况,减10)

对于一个轴点willpush(含有x,y,i,k的结构体,willpush.x和y表示坐标,willpush.i表示该点在n个点中是第几个点,willpush.k表示经过了几个新增设的点到达这里),遍历所有 非此点/非终点 的点(遍历变量 i ),如果可走,则到达点 i ,经过mid_k(记录经过k的个数,如果是”ד,就+1)个新增设点的dec_[i][mid_k]和到达轴点willpush.i的点经过willpush.k个新增设点的dec_[willpush.i][willpush.k] 加一,比较

1  if(dec_[i][mid_k] > dec_[willpush.i][willpush.k] + 1){
2 dec_[i][mid_k] = dec_[willpush.i][willpush.k] + 1;

就是说,轴点记录从起点到达当前点这里,经过k个(当然k可以有多个)新增设点所需要的最少步数dec_(这里说位步数是因为权值位1,从一个点到达下一个点就是一步),那就以我为中心,向周围找一圈,比如遇到第一个可走的点(距离r内),这里先叫它node吧,那以我这个最短距离dec_再加一作为到达node这里(经过了经历的k个新增设点)理应最小的数值,然后与实际存的dec_数值作比较。

用那个栗子说一下就明白了,

圆圈表示点,“×”表示新增设的点,菱形里面的数字代表作为第几个点输入的,以下用“菱形+数字”代表第几个点。

首先从

◆0出发,◆10 and ◆2 入队列,

◆2出队列,◆3入队列,◆10出队列,◆11入队列。

到这里为止先分析一下数据,每一次入队列之前的dec_都需要改变,比如以◆0作为轴点向四周遍历的时候,◆2可走,简单比价dec_赋值为1,◆10入队的时候,发现这个点dec_[10][1]初始值位INT_MAX最大值,即第10个输入的点,经历1个新增设点到达的位置目前最短距离位INT_MAX,我与◆0的dec_[0][0](初始值只有这个设置为0)加一作比较,即“1”与INT_MAX作比较,小于,则赋值(松弛),现在dec_[10][1]是 1了。接着继续......

◆3出,◆4入,◆11出,◆6入。

到这里埋一个伏笔,很重要也是dec_的精髓,和本题的巧妙思维所在(我自己没先到,看了题解有吭哧瘪肚看了好几天) 

◆4出,◆5入,◆6出,◆13入不了!只能入◆7,因为k给定是2,最大新增设的点为两个。再继续......

◆5出,◆12入,◆7出,◆8入。

◆12出,◆9入,◆8出,◆9入。

◆9出,◆8入

到这里再埋下一个伏笔,作为第二个伏笔

◆8出,◆7入,◆7出,◆6入。

到这里结合第一个伏笔解释,第一个伏笔◆6入的时候,存入的dec_值仔细想想再看下面答案

值应该为dec_[6][2],最后赋值成从◆11来的加一,即走3步最短到这里,而这里的◆6入要分清怎么来的,区别于第一次◆6入。第一次◆6入后只能向上走,走◆7,走◆8走◆9,到了◆9就不能走◆12了,也不能回到◆8 了 ,因为同样是走两个新增设的k点,到◆8,到◆9就不能再回◆8了因为if判断那里距离不是更近,所以不压入队列。这也就顺便解释了第二个伏笔。

这里的第二次◆6入其实是从◆2,◆3,◆4,◆5,◆12,◆9,◆8,◆7到的◆6,体现dec_精华巧妙地地方来了,第一次的◆6入是从下面◆0,◆10,◆11走到的,dec_[6][2]值为3,而向右堵住了,向上又没回来卡再在◆9,只能凑够◆2,◆3,◆4,◆5,◆12,◆9,◆8,◆7到的◆6,那么dec_是怎样的呢?思考不出来或者已经会了再看答案

答案其实是dec_[6][1]值为9,经过一个新增设的点到达◆6,最短需要9步。这里巧妙在于没有把 ◆6“最短距离”写死,用了一个二维数组记录不同路径到达这个点的不同最小值,这里的不同路径主要就在于这些新增设的点。而不至于想我一开始写的似得,◆0,◆10,◆11,◆6再往右走不了,从◆2,◆3,◆4,◆5,◆12,◆9,◆8,◆7到◆6的数值因为没有之前◆6存的数小而不入队,导致卡死这里了。或者我这个◆2,◆3,◆4,◆5,◆12,◆9,◆8,◆7到◆6依然是3就麻烦了。相当于走的一大圈回来应该是你一大圈的路程,却偷了之前短的数据。

 

(这里比较不好解释,多写然后printf找出问题所在,实在理解不了,加我微信acmer13936130136我给你讲一下吧,备注“博客园来的,询问CCF无线网络题目”加好后主动发我这篇博客链接)。希望每一个人都能A掉这个题目。我自己写完都未必能重写满分或者思路尤在,更别说面试考这个了,再加油吧!

注意:1.涉及到r运算的地方,要设置为long long int,否则整型只有80分

   2.不能设置visit走过则不入队的数组,否则也死,还拿◆6举例子,自己想一下吧,不会加微信问。

AC代码

  1 #include<cstdio>
2 #include<climits>
3 #include<cstring>
4 #include<queue>
5 #include <iostream>
6 #include <algorithm>
7 using namespace std;
8 struct node
9 {
10 int x;
11 int y;
12 int i;
13 int k;
14 }map[205];
15 int n, m, k;
16 long long int r;
17 int Sx, Sy;
18 int Tx, Ty;
19 int SPFA(int i);
20 bool legal(long long int Ax, long long int Bx, long long int Ay, long long int By);
21 int dec_[205][105];
22 int main()
23 {
24 scanf("%d %d %d %lld", &n, &m, &k, &r);
25 for(int i = 0; i < n + m; i ++)
26 scanf("%d %d", &map[i].x, &map[i].y);
27 for(int i = 0; i < 201; i ++)
28 for(int j = 0; j < 101; j ++)
29 dec_[i][j] = INT_MAX;
30 dec_[0][0] = 0;
31 Sx = map[0].x;
32 Sy = map[0].y;
33 Tx = map[1].x;
34 Ty = map[1].y;
35 printf("%d\n", SPFA(0));
36 }
37 bool legal(long long int Ax, long long int Bx, long long int Ay, long long int By)
38 {
39 if((Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) <= r * r)
40 return true;
41 else
42 return false;
43 }
44 int SPFA(int i)
45 {
46 queue<node> s;
47 node mid;//中转
48 node willpush;//即将压入
49 node next;
50 mid.x = Sx;
51 mid.y = Sy;
52 mid.i = 0;
53 mid.k = 0;
54 s.push(mid);
55 int mid_k;
56 while(!s.empty()){
57 willpush = s.front();
58 s.pop();
59 for(int i = 0; i < n + m; i ++){
60 if(legal(willpush.x, map[i].x, willpush.y, map[i].y))
61 {
62 if(willpush.x == map[i].x && willpush.y == map[i].y)
63 continue;
64 if(map[i].x == Tx && map[i].y == Ty)
65 return dec_[willpush.i][willpush.k];//这些个坐标,变量很有讲究
66 mid_k = willpush.k;
67 if(i >= n){
68 if(willpush.k == k)
69 continue;
70 mid_k = willpush.k + 1;
71 }
72 if(dec_[i][mid_k] > dec_[willpush.i][willpush.k] + 1){
73 dec_[i][mid_k] = dec_[willpush.i][willpush.k] + 1;
74 next.x = map[i].x;
75 next.y = map[i].y;//调试好久。。。。
76 next.i = i;
77 next.k = mid_k;
78 s.push(next);
79 }
80 }
81 }
82 }
83 return 0;
84 }
85
86 //5 3 1 3
87 //0 0
88 //5 5
89 //0 3
90 //0 5
91 //3 5
92 //3 3
93 //4 4
94 //3 0
95
96 //10 4 2 1
97 //0 0
98 //5 0
99 //0 1
100 //0 2
101 //0 3
102 //1 3
103 //3 0
104 //3 1
105 //3 2
106 //3 3
107 //1 0
108 //2 0
109 //2 3
110 //4 0

PS:本题目数据应该是有点水,因为如果把68/69行去掉,也是可以AC的,只不过30ms

按理说应该遇到更多的新增设点返回不做数的,这里后台测试数据应该是没有给出一条可以超过k的路径走法。

这里我参考了很多题解才看懂,看题解过程中无意间看到一组数据就是我上面的那个例子(来源于这题解下面的评论(不过这链接里的两代码都是错误的,尽管CCF可以AC,我的那个例子和链接里的评论就是反例,所有BFS写的都是如此,都是错误的))其实应该晚一点看到的,不然先入正确思路会错过很多坑,这样下面写其他题目的时候还会出错)

附录:


看到题目我没什么思路,感觉想搜索。

简单想一下,我最先想到的是想用DFS,先将k,r变一下表述,38,40行容易理解。7行的变量为是否为非新增设的点,即是否是本身就有的点。8行变量为新增设的点。我是想深搜,从起点开始,搜出所有的可走路径,对于每一个点我一开始误以为都是r为3,错误的将走步设置为3之内,即最多上下左右走2格。对于可以走的(r之内,边界之内),(我的63行写错了,实际想表达。对意思是这个点是否为n个点面的,if(is_be_point[map[i][0]][map[i][1]] == 1) ,或者m点里未超过k的),是就压入DFS递归再以这个点继续。最后用answer数组记录所有可以到达终点的路径值,取min。

但是有几个问题:

1.数组开不了10^8。而如果这一步:判断该点是否是n个内的点,应该for(0 < i < n)判断thisx,thisy是否与(x,y)匹配,即当前点存在于map数组内。(map数组记录的是n个的,can_be_set记录的是m个的)。或者set什么vetor之类的容器?判断是否在此坐标数据中出现过?感觉考的不是这个知识,而且这么写很蠢,多半会超时。

2.路径太多了,可能超时。因为走过还可以走,类似dp动态规划,即走这一步不一定是最优的(新增设点的存在),有可能无穷多条。即

我可以起点→A→B→C→D→E......终点、起点→B→C→D→E......终点、起点→ C→D→E......终点、起点→B→D→E......终点。

可见对于一条路径几乎就有无穷中变数走法,类似贪心和动态规划。

正常搜索是没有“跳着”的,都是“一步一个脚印”,距离够(一般都是1,格子嘛)就走,除非遇到了非法格子地图外,或者有路径先到达,否则一直一步一步走着。可这个感觉怪怪的,像贪心和动态规划。只考虑r无形中就增加好多路径,还没考虑k的事呢,感觉这法子不行。

有同学说,那我每次最大格子走呢,即走小于r最大整数。我举一个反例

r还是3,k是1,k最多就可以添加一个。

那我从起点到达第一个×,接着下一步跨3个格子,再接着一步跨3个格子就到了第二个新增设点“×”,那只能返回重新选择走法,很像动态规划。

3.思路本身就不对

写崩了的代码......

 1 #include<cstdio>
2 #include<algorithm>
3 using namespace std;
4
5 int n, m, k, r;
6 int map[105][2];
7 int is_be_point[100000000][100000000];
8 int can_be_set[105][2];
9 void dfs(int x, int y);
10
11 int dec[28][2] =
12 {{0, -1}, {0, -2}, {0, -3}, {0, 1}, {0, 2}, {0, 3},//横
13 {-1, 0}, {-2, 0}, {-3, 0}, {1, 0}, {2, 0}, {3, 0},//竖
14 {-2, 1}, {-2, 2}, {-2, -1}, {-2, -2}, {-1, 1}, {-1, 2}, {-1, -1}, {-1, -2},
15 {2, 1}, {2, 2}, {2, -1}, {2, -2}, {1, -1}, {1, -2}, {1, 1}, {1, 2} };
16
17 int Sx, Sy, Tx, Ty;
18 int max_number_can_set;
19 int max_can_dec;
20 bool legal(int x, int y);
21 int main()
22 {
23 scanf("%d %d %d %d", &n, &m, &k, &r);
24 for(int i = 0; i < n; i ++){
25 scanf("%d %d", &map[i][0], &map[i][1]);
26 is_be_point[map[i][0]][map[i][1]] = 1;
27 if(i == 0)
28 {
29 Sx = map[i][0];
30 Sy = map[i][1];
31 }
32 if(i == 1)
33 {
34 Tx = map[i][0];
35 Ty = map[i][1];
36 }
37 }
38 max_number_can_set = k;
39 max_can_dec = r;
40 for(int i = 0; i < m; i ++){
41 scanf("%d %d", &can_be_set[i][0], &can_be_set[i][1]);
42
43 }
44 // 思考DFS还是BFS
45 dfs(Sx, Sy);
46 }
47 bool legal(int x, int y)
48 {
49 // if(abs(x) <= abs(Sx) && x <= Tx && y <= Ty && abs(y) <= Sy)//略有不同。。。好难写啊
50 if(x < max(Sx, Tx) && x > min(Sx, Tx) &&
51 y < max(Sy, Ty) && y > min(Sy, Ty))
52 return true;
53 else
54 return false;
55 }
56 void dfs(int x, int y)
57 {
58 if(!legal(x, y))
59 return;
60 for(int i = 0; i < 29; i ++){
61 int thisx = x + dec[i][0];
62 int thisy = y + dec[i][1];
63 if(map[thisx][thisy])
64 dfs(thisx, thisy);
65
66 }
67 }

写的好烦。。。代码好烦。。。考研好烦。。。时间好紧张、、。。何时才能心无旁骛的学习

我要年薪30w。。啊啊啊啊啊!!!


写过了DFS,试试BFS。

stl都不会,想手写C语言的数组表示的队列

 1 #include<cstdio>
2 #include<climits>
3 #include<queue>
4 #include <iostream>
5 #include <algorithm>
6 using namespace std;
7 //int map[205][2];
8 struct node{
9 int x;
10 int y;
11 int step;
12 int kcount;
13 } map[205];
14 int n, m, k, r;
15 int Sx, Sy;
16 int Tx, Ty;
17 int SPFA(int i);
18 bool legal(int Ax, int Ay, int Bx, int By);
19 int main()
20 {
21 scanf("%d %d %d %d", &n, &m, &k, &r);
22 for(int i = 0; i < n + m; i ++){
23 scanf("%d %d", &map[i].x, &map[i].y);
24 map[i].step = INT_MAX;
25 map[i].kcount = 0;
26 }
27 map[0].step = 0;
28 Sx = map[0].x;
29 Sy = map[0].y;
30 Tx = map[1].x;
31 Ty = map[1].y;
32 SPFA(0);
33 }
34 bool legal(int Ax, int Ay, int Bx, int By)
35 {
36 if((Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) <= r * r)
37 return true;
38 else
39 return false;
40 }
41 int SPFA(int i)
42 {
43 queue<node> s;
44 node p;
45 // s.x = Sx;
46 // s.y = Sy;
47 // s.push(map[0]);
48 p.x = Sx;
49 p.y = Sy;
50 s.push(p);
51 while(!s.empty()){
52 p = s.front();
53 s.pop();
54 if(p.x == Tx && p.y == Ty)
55 return p.step;
56 for(int i = 0; i < n + m; i ++){
57 if(i >= n && s.kcount == k)
58 continue;
59 if(legal(s.x, map[i].x, s,y, map[i].y)){
60 if(i >= n){
61 map[i].kcount = s.kcount ++;
62 }
63 s.push(map[i]);
64 if(map[i].step > s.step + 1)
65 map[i].step = s.step + 1;
66 }
67 }
68 }
69 }

代码有改动,但思路主要是BFS,这个思路问题主要出在没有搞清楚究竟怎样处理新增设点条件下的最短(这个题如果没有新增设点的条件就是最最简单基础的BFS)。具体位置是64/65行,

这里不应该这么比较,把距离作为该点的单一类似BFS里面的固有属性,某点目前最小值就用某一值来记录,

而是应该同时记录出是经历几个新增设的点到达这里的。

其他问题不说,就是这个引起的问题吧,拿这个举例子

我◆0→◆10→◆11→◆6是4步。而◆0→◆2→◆3→◆4→◆5→◆12→◆9→◆8→◆7→◆6是9步但是在64行依旧是最距离4,相当于偷换。或者说没比较出真是的距离。


我看了一下别人代码说SPFA,就写了一下。但错在了依旧是BFS的思路,依旧是64行那个错误。

  1 ////#include<cstdio>
2 ////int map[205][2];
3 ////int n, m, k, r;
4 ////void SPFA();
5 ////int main()
6 ////{
7 //// scanf("%d %d %d %d", &n, &m, &k, &r);
8 //// for(int i = 0; i < n + m; i ++){
9 //// scanf("%d %d", &map[i][0], &map[i][1]);
10 //// if(i == 0){
11 //// Sx = map[i][0];
12 //// Sy = map[i][1];
13 //// }
14 //// if(i == 1)
15 //// {
16 //// Tx = map[i][0];
17 //// Ty = map[i][1];
18 //// }
19 //// }
20 //// SPFA(Sx, Sy);
21 ////}
22 ////bool legal(int Ax, int Ay, int Bx, int By)
23 ////{
24 //// if((Bx - Ax) * (Bx - Ax) + (By - Ay) * (By - Ay) <= r * r)
25 //// return true;
26 //// else
27 //// return false;
28 ////}
29 ////void SPFA()
30 ////{
31 //// for(int i = 0; i < n + m; i ++){
32 ////
33 //// }
34 ////}
35 //
36 //
37 ///* CCF201403-4 无线网络 */
38 //
39 //#include <iostream>
40 //#include <cstring>
41 //#include <queue>
42 //
43 //using namespace std;
44 //
45 //const int MAXN = 100 + 100;
46 //
47 //struct {
48 // long long x, y;
49 //} coord[MAXN+1];
50 //
51 //struct status {
52 // long long x, y;
53 // int step, kcount;
54 //};
55 //
56 //bool visited[MAXN+1];
57 //
58 //int dfs(int n, int m, int k, int begin, int end, long long r)
59 //{
60 // int max;
61 //
62 // // 变量初始化
63 // memset(visited, false, sizeof(visited));
64 //
65 // // 设置根结点
66 // status start, front, v;
67 // start.x = coord[begin].x;
68 // start.y = coord[begin].y;
69 // start.step = 0;
70 // start.kcount = 0;
71 // queue<status> q;
72 // q.push(start);
73 //
74 // // 设置根结点为已经访问过
75 // visited[begin] = true;
76 //
77 // while(!q.empty()) {
78 // front = q.front();
79 // q.pop();
80 //
81 // // 到达终点则结束
82 // if(front.x == coord[end].x && front.y == coord[end].y)
83 // return front.step - 1;
84 //
85 // // 搜索可以连接的路由器
86 // if(front.kcount == k)
87 // max = n;
88 // else
89 // max = n + m;
90 // for(int i=0; i<max; i++) {
91 // // 访问过的坐标则跳过
92 // if(visited[i])
93 // continue;
94 //
95 // // 判定下一个路由器的坐标是否在半径r之内, 不在半径之内则跳过,在半径之内则继续搜索
96 // if((front.x - coord[i].x) * (front.x - coord[i].x) + (front.y - coord[i].y) * (front.y - coord[i].y) > r * r)
97 // continue;
98 // else {
99 // // 第i个路由器设为已经访问过
100 // visited[i] = true;
101 //
102 // // 计算步数,并且将第i个路由器加入队列
103 // v.x = coord[i].x;
104 // v.y = coord[i].y;
105 // v.step = front.step + 1;
106 // if(i >= n)
107 // v.kcount = front.kcount + 1;
108 // else
109 // v.kcount = front.kcount;
110 // q.push(v);
111 // }
112 // }
113 // }
114 //
115 // return 0;
116 //}
117 //
118 //int main()
119 //{
120 // int n, m, k;
121 // long long r;
122 //
123 // // 输入数据
124 // cin >> n >> m >> k >> r;
125 // for(int i=0; i<n+m; i++) // n个路由器的位置+可以增设的m个路由器的位置
126 // cin >> coord[i].x >> coord[i].y;
127 //
128 // // BFS
129 // int ans = dfs(n, m, k, 0, 1, r);
130 //
131 // // 输出结果
132 // cout << ans << endl;
133 //
134 // return 0;
135 //}
136 //
137 ///*
138 //测试数据:
139 //5 3 1 3
140 //0 0
141 //5 5
142 //0 3
143 //0 5
144 //3 5
145 //3 3
146 //4 4
147 //3 0
148 //2
149 //10 1 1 2
150 //0 0
151 //3 1
152 //-2 0
153 //-2 2
154 //-2 4
155 //-2 6
156 //0 6
157 //2 6
158 //2 4
159 //2 2
160 //2 0
161 //1
162 //10 1 1 2
163 //0 0
164 //3 1
165 //-2 0
166 //-2 2
167 //-2 4
168 //-2 6
169 //0 6
170 //2 6
171 //2 4
172 //2 2
173 //3 0
174 //8
175 //6 3 2 50000000
176 //0 0
177 //50000000 100000000
178 //100000000 100000000
179 //100000000 0
180 //100000000 50000000
181 //50000000 0
182 //-100000000 50000000
183 //0 50000000
184 //0 100000000
185 //2
186 //*/
187 //
188 ////10 4 2 1
189 ////0 0
190 ////5 0
191 ////0 1
192 ////0 2
193 ////0 3
194 ////1 3
195 ////3 0
196 ////3 1
197 ////3 2
198 ////3 3
199 ////1 0
200 ////2 0
201 ////2 3
202 ////4 0
203
204 //#include<algorithm>
205 //#include<cstdio>
206 //#include<cstring>
207 //#include<iostream>
208 //#include<queue>
209 //#define N 205
210 //#define INF 0x3f3f3f3f
211 //typedef long long LL;
212 //using namespace std;
213 //
214 //struct P {
215 // int x,y;
216 //} p[N];
217 //
218 //
219 //int n,m,k,r;
220 //int d[N][N];
221 //bool vis[N][N],Map[N][N];
222 //
223 //void spfa() {
224 // queue<P> q;
225 // memset(vis,0,sizeof(vis));
226 // memset(d,INF,sizeof(d));
227 // //这里的d[i][j]和vis[i][j]有特殊的含义
228 // // d[i][j]表示从起点开始,经过增设的j个点,到达第i个点的最短路径
229 // // vis[i][j]表示是否可以从起点经过增设的j个路由器到达i
230 // d[0][0]=0;
231 // vis[0][0]=1;
232 // //这里的s和tem感觉已经不再是表示一个点了,所以有点错觉
233 // P s,tem;
234 // int des_p=0,ap_num=0;
235 // int tp_des_p,tp_ap_num;
236 // s.x=s.y=des_p;
237 // q.push(s);
238 // while(!q.empty()) {
239 // s=q.front();
240 // q.pop();
241 // des_p=s.x;
242 // ap_num=s.y;
243 // vis[des_p][ap_num]=0;
244 // for(int i=0; i<n+m; ++i)
245 // //和s点相连的点
246 // //另外看到这里莫名感觉这题简单(什么都不会,但有一种莫名的自信)
247 // //这哪是spfa啊,更像是普通的bfs(写完我就后悔了= =)
248 // //这里的s.x其实就是点的编号。程序可读性差= =(明明可以用别的表示的,非得图省事用P,差评!)
249 // //嗯……这个程序有点带劲啊╮(╯▽╰)╭
250 // if(Map[des_p][i]) {
251 // //下面这几句是重点啊
252 // tp_des_p=i;
253 // tp_ap_num=ap_num;
254 // if(i>=n) ++tp_ap_num;
255 // if(tp_ap_num<=k && d[tp_des_p][tp_ap_num]>d[des_p][ap_num]+1) {
256 // //只要符合以上条件就进行松弛
257 // d[tp_des_p][tp_ap_num]=d[des_p][ap_num]+1;
258 // //如果不在队列里就让其进入队列
259 // if(!vis[tp_des_p][tp_ap_num]) {
260 // vis[tp_des_p][tp_ap_num]=1;
261 // //进入队列的其实是起点所到目的地点和经过的增设点数
262 // tem.x=tp_des_p;
263 // tem.y=tp_ap_num;
264 // q.push(tem);
265 // }
266 // }
267 // }
268 // }
269 // int ans=INF;
270 // for(int i=0; i<=k; i++) ans=min(ans,d[1][i]);
271 // printf("%d\n",ans-1);
272 //}
273 //
274 //int main() {
275 // int i,j;
276 // cin>>n>>m>>k>>r;
277 // //输入存在的点和可以放置的点
278 // for(i=0; i<n+m; ++i) scanf("%d%d",&p[i].x,&p[i].y);
279 // //map是邻接矩阵
280 // memset(Map,0,sizeof(Map));
281 // //这个循环看起来不免重复,但是没超时
282 // for(i=0; i<n+m; ++i)
283 // for(j=i+1; j<n+m; ++j)
284 // //LL就是long long int,这里是强制类型转换
285 // if(LL(p[i].x-p[j].x)*(p[i].x-p[j].x)+LL(p[i].y-p[j].y)*(p[i].y-p[j].y)<=LL(r)*r)
286 // Map[i][j]=Map[j][i]=1;
287 //
288 // spfa();
289 // return 0;
290 //}
291
292
293
294
295 //先想好在写还是边写边想——后者
296 //参考 SPFA算法详解(强大图解,不会都难)
297 #include<cstdio>
298 #include<climits>
299 #include<queue>
300 #include <iostream>
301 #include <algorithm>
302 using namespace std;
303 //int map[205][2];
304 struct node{
305 int x;
306 int y;
307 int step;
308 int kcount;
309 } map[205];
310 //int queue[205];//出现绿色是用库还是?
311 int n, m, k, r;
312 int Sx, Sy;
313 int Tx, Ty;
314 int SPFA(int i);
315 bool legal(int Ax, int Ay, int Bx, int By);
316 int main()
317 {
318 scanf("%d %d %d %d", &n, &m, &k, &r);
319 for(int i = 0; i < n + m; i ++){
320 scanf("%d %d", &map[i].x, &map[i].y);
321 map[i].step = INT_MAX;
322 map[i].kcount = 0;
323 }
324 map[0].step = 0;
325 Sx = map[0].x;
326 Sy = map[0].y;
327 Tx = map[1].x;
328 Ty = map[1].y;
329 SPFA(0);
330 }
331 bool legal(int Ax, int Ay, int Bx, int By)
332 {
333 if((Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) <= r * r)
334 return true;
335 else
336 return false;
337 }
338 int SPFA(int i)
339 {
340 // queue[i ++] = Sx
341 queue<int> s;
342 node s;
343 node p;
344 s.x = Sx;
345 s.y = Sy;
346 s.push(map[0]);
347 while(!empty()){
348 p = s.front();
349 if(p.x == Tx && p.y == Ty)
350 return p.step;
351 for(int i = 0; i < n + m; i ++){
352 if(i >= n && s.kcount == k)
353 continue;
354 if(legal(s.x, map[i].x, s,y, map[i].y)){
355 if(i >= n){
356 map[i].kcount = s.kcount ++;
357 if()
358 }
359 push(map[i]);
360 if(map[i].step > s.step + 1)
361 map[i].step = s.step + 1;
362 }
363 }
364 }
365 }

我具体学了一下SPFA  参考博客

之前一战结束时刷pat时学过SPFA,所以一看就会了,只是调试写起来很劲。

第一次运行(依旧是64行的那个问题)

 1 #include<cstdio>
2 #include<climits>
3 #include<queue>
4 #include <iostream>
5 #include <algorithm>
6 using namespace std;
7 //int map[205][2];
8 struct node
9 {
10 int x;
11 int y;
12 int step;
13 int kcount;
14 } map[205];
15 int n, m, k, r;
16 int Sx, Sy;
17 int Tx, Ty;
18 int SPFA(int i);
19 bool legal(int Ax, int Ay, int Bx, int By);
20 int main()
21 {
22 scanf("%d %d %d %d", &n, &m, &k, &r);
23 for(int i = 0; i < n + m; i ++)
24 {
25 scanf("%d %d", &map[i].x, &map[i].y);
26 map[i].step = INT_MAX;
27 map[i].kcount = 0;
28 }
29 map[0].step = 0;
30 Sx = map[0].x;
31 Sy = map[0].y;
32 Tx = map[1].x;
33 Ty = map[1].y;
34 printf("%d", SPFA(0));
35 }
36 bool legal(int Ax, int Ay, int Bx, int By)
37 {
38 if((Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) <= r * r)
39 return true;
40 else
41 return false;
42 }
43 int SPFA(int i)
44 {
45 queue<node> s;
46 node p;
47 // s.x = Sx;
48 // s.y = Sy;
49 // s.push(map[0]);
50 p.x = Sx;
51 p.y = Sy;
52 s.push(p);
53 while(!s.empty())
54 {
55 p = s.front();
56 s.pop();
57 // if(p.x == Tx && p.y == Ty)
58 // return p.step;
59
60 for(int i = 0; i < n + m; i ++)
61 {
62 if(map[i].x == Tx && map[i].y == Ty)
63 return p.step;
64 if(i >= n && p.kcount == k)
65 continue;
66 if(legal(p.x, map[i].x, p.y, map[i].y))
67 {
68 if(i >= n)
69 map[i].kcount = p.kcount ++;
70 s.push(map[i]);
71 if(map[i].step > p.step + 1){
72 map[i].step = p.step + 1;
73 // printf("##\n");
74 }
75 }
76 }
77 }
78 return 0;
79 }
80 //5 3 1 3
81 //0 0
82 //5 5
83 //0 3
84 //0 5
85 //3 5
86 //3 32
87 //4 4
88 //3 0

实在没招加了visit就40分,不加就30分。但感觉visit加的没有意义

  1 #include<cstdio>
2 #include<climits>
3 #include<queue>
4 #include <iostream>
5 #include <algorithm>
6 using namespace std;
7 //int map[205][2];
8 struct node
9 {
10 int x;
11 int y;
12 int step;
13 int kcount;
14 } map[205];
15 int n, m, k, r;
16 int Sx, Sy;
17 int Tx, Ty;
18 int visit[205];
19 int SPFA(int i);
20 bool legal(int Ax, int Bx, int Ay, int By);
21 int main()
22 {
23 scanf("%d %d %d %d", &n, &m, &k, &r);
24 for(int i = 0; i < n + m; i ++)
25 {
26 scanf("%d %d", &map[i].x, &map[i].y);
27 map[i].step = INT_MAX;
28 map[i].kcount = 0;
29 }
30 map[0].step = 0;
31 Sx = map[0].x;
32 Sy = map[0].y;
33 Tx = map[1].x;
34 Ty = map[1].y;
35 printf("%d", SPFA(0));
36 }
37 bool legal(int Ax, int Bx, int Ay, int By)
38 {
39 if((Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) <= r * r)
40 return true;
41 else
42 return false;
43 }
44 int SPFA(int i)
45 {
46 queue<node> s;
47 node p;// s.x = Sx;// s.y = Sy;// s.push(map[0]);
48 p.x = Sx;
49 p.y = Sy;
50 s.push(p);
51 visit[0] = 1;
52 while(!s.empty())
53 {
54 p = s.front();
55 s.pop();
56 for(int i = 0; i < n + m; i ++)
57 {
58 if(visit[i])
59 continue;
60 if(legal(p.x, map[i].x, p.y, map[i].y))
61 {
62 if(p.x == map[i].x && p.y == map[i].y)
63 continue;
64 if(map[i].x == Tx && map[i].y == Ty)
65 return p.step;
66 if(i >= n)
67 {
68 if(p.kcount == k)
69 continue;
70 map[i].kcount = p.kcount ++;
71 }
72 if(map[i].step > p.step + 1)
73 {
74 map[i].step = p.step + 1;// printf("%d\n", map[i].step);
75 }
76 s.push(map[i]);
77 if(i < n)
78 visit[i] = 1;
79 }
80 }
81 }
82 return 0;
83 }
84 //5 3 1 3
85 //0 0
86 //5 5
87 //0 3
88 //0 5
89 //3 5
90 //3 3
91 //4 4
92 //3 0
93
94 //10 4 2 1
95 //0 0
96 //5 0
97 //0 1
98 //0 2
99 //0 3
100 //1 3
101 //3 0
102 //3 1
103 //3 2
104 //3 3
105 //1 0
106 //2 0
107 //2 3
108 //4 0

调试发现step那里不行,依旧64行的问题

  1 #include<cstdio>
2 #include<climits>
3 #include<queue>
4 #include <iostream>
5 #include <algorithm>
6 using namespace std;
7 //int map[205][2];
8 struct node
9 {
10 int x;
11 int y;
12 int step;
13 int kcount;
14 } map[205];
15 int n, m, k, r;
16 int Sx, Sy;
17 int Tx, Ty;
18 int SPFA(int i);
19 bool legal(int Ax, int Bx, int Ay, int By);
20 int main()
21 {
22 scanf("%d %d %d %d", &n, &m, &k, &r);
23 for(int i = 0; i < n + m; i ++)
24 {
25 scanf("%d %d", &map[i].x, &map[i].y);
26 map[i].step = INT_MAX;
27 map[i].kcount = 0;
28 }
29 map[0].step = 0;
30 Sx = map[0].x;
31 Sy = map[0].y;
32 Tx = map[1].x;
33 Ty = map[1].y;
34 printf("%d", SPFA(0));
35 }
36 bool legal(int Ax, int Bx, int Ay, int By)
37 {
38 if((Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) <= r * r)
39 return true;
40 else
41 return false;
42 }
43 int SPFA(int i)
44 {
45 queue<node> s;
46 node p;// s.x = Sx;// s.y = Sy;// s.push(map[0]);
47 p.x = Sx;
48 p.y = Sy;
49 s.push(p);
50 while(!s.empty())
51 {
52 p = s.front();
53 s.pop();
54 for(int i = 1; i < n + m; i ++)
55 {
56 if(legal(p.x, map[i].x, p.y, map[i].y))
57 {
58 if(p.x == map[i].x && p.y == map[i].y)
59 continue;
60 if(map[i].x == Tx && map[i].y == Ty)
61 return p.step;
62 map[i].kcount = p.kcount;
63 if(i >= n)
64 {
65 if(p.kcount == k)//问题1,还有就是每一个的线路要赋值p.kcount
66 continue;
67 map[i].kcount = p.kcount + 1;
68 printf("$%d\n", p.kcount);
69 // if(p.x == 2 && p.y == 0)
70 // printf("^%d\n", map[i].kcount);
71 // if(p.x == 1 && p.y == 0)
72 // printf("^%d\n", map[i].kcount);
73 // if(i == 10)
74 // printf("^%d\n", map[i].kcount);
75 printf("^%d\n", map[12].kcount);//没进去
76 }
77 if(map[i].step > p.step + 1)//这样写进行不下去,visit又死锁
78 {
79 map[i].step = p.step + 1;// printf("%d\n", map[i].step);
80 }
81 s.push(map[i]);
82 }
83 }
84 }
85 return 0;
86 }
87 //5 3 1 3
88 //0 0
89 //5 5
90 //0 3
91 //0 5
92 //3 5
93 //3 3
94 //4 4
95 //3 0
96
97 //10 4 2 1
98 //0 0
99 //5 0
100 //0 1
101 //0 2
102 //0 3
103 //1 3
104 //3 0
105 //3 1
106 //3 2
107 //3 3
108 //1 0
109 //2 0
110 //2 3
111 //4 0

这里的这句话 if(map[i].step > p.step + 1)

盗用了最短的那个step,所以

10 4 2 1
0 0
5 0
0 1
0 2
0 3
1 3
3 0
3 1
3 2
3 3
1 0
2 0
2 3
4 0

会输出4

  1 #include<cstdio>
2 #include<climits>
3 #include<queue>
4 #include <iostream>
5 #include <algorithm>
6 using namespace std;
7 //int map[205][2];
8 struct node
9 {
10 int x;
11 int y;
12 int step;
13 int kcount;
14 } map[205];
15 int n, m, k, r;
16 int Sx, Sy;
17 int Tx, Ty;
18 int SPFA(int i);
19 bool legal(int Ax, int Bx, int Ay, int By);
20 int main()
21 {
22 scanf("%d %d %d %d", &n, &m, &k, &r);
23 for(int i = 0; i < n + m; i ++)
24 {
25 scanf("%d %d", &map[i].x, &map[i].y);
26 map[i].step = INT_MAX;
27 map[i].kcount = 0;
28 }
29 map[0].step = 0;
30 Sx = map[0].x;
31 Sy = map[0].y;
32 Tx = map[1].x;
33 Ty = map[1].y;
34 printf("%d", SPFA(0));
35 }
36 bool legal(int Ax, int Bx, int Ay, int By)
37 {
38 if((Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) <= r * r)
39 return true;
40 else
41 return false;
42 }
43 int SPFA(int i)
44 {
45 queue<node> s;
46 node p;// s.x = Sx;// s.y = Sy;// s.push(map[0]);
47 p.x = Sx;
48 p.y = Sy;
49 s.push(p);
50 while(!s.empty())
51 {
52 p = s.front();
53 s.pop();
54 for(int i = 1; i < n + m; i ++)
55 {
56 if(legal(p.x, map[i].x, p.y, map[i].y))
57 {
58 if(p.x == map[i].x && p.y == map[i].y)
59 continue;
60 if(map[i].x == Tx && map[i].y == Ty)
61 return p.step;
62 map[i].kcount = p.kcount;
63 if(map[i].x == 4 && map[i].y == 0)
64 printf("_%d %d_\n", map[i].kcount, map[i].step);//输出2,对的,但是后面变1了
65 // printf("_%d %d_\n", map[2].kcount, map[2].step);
66 if(i >= n)
67 {
68 if(p.kcount == k)//问题1,还有就是每一个的线路要赋值p.kcount
69 continue;
70 map[i].kcount = p.kcount + 1;
71 }
72 if(map[i].step > p.step + 1)//这样写进行不下去,visit又死锁
73 map[i].step = p.step + 1;// printf("%d\n", map[i].step);
74 s.push(map[i]);
75 }
76 }
77 }
78 return 0;
79 }
80 //5 3 1 3
81 //0 0
82 //5 5
83 //0 3
84 //0 5
85 //3 5
86 //3 3
87 //4 4
88 //3 0
89
90 //10 4 2 1
91 //0 0
92 //5 0
93 //0 1
94 //0 2
95 //0 3
96 //1 3
97 //3 0
98 //3 1
99 //3 2
100 //3 3
101 //1 0
102 //2 0
103 //2 3
104 //4 0

现在感觉step判断多余,去了还是不行,超时,还是40却提示了个运行超时,之前没提示,只是1.6s。。

我认为step判断多余,我想的是

如果已经走过去了,那后面再来的点更改距离就无所谓了,

而前面已经走过的点如果记录的最短距离,我现在这个step大于那个也没事,因为如果你真小且新增设的点没有超过k的话,会早就到达终点输出最后最小值的。

但其实不然,真正的SPFA,就拿最后一个点来说,前面经过条条大路过来,我剩下三条路径,最后的那条路径是比较长的,所以不能不比较。

  1 #include<cstdio>
2 #include<climits>
3 #include<queue>
4 #include <iostream>
5 #include <algorithm>
6 using namespace std;
7 //int map[205][2];
8 struct node
9 {
10 int x;
11 int y;
12 int step;
13 int kcount;
14 } map[205];
15 int n, m, k, r;
16 int Sx, Sy;
17 int Tx, Ty;
18 int SPFA(int i);
19 bool legal(int Ax, int Bx, int Ay, int By);
20 int main()
21 {
22 scanf("%d %d %d %d", &n, &m, &k, &r);
23 for(int i = 0; i < n + m; i ++)
24 {
25 scanf("%d %d", &map[i].x, &map[i].y);
26 map[i].step = INT_MAX;
27 map[i].kcount = 0;
28 }
29 map[0].step = 0;
30 Sx = map[0].x;
31 Sy = map[0].y;
32 Tx = map[1].x;
33 Ty = map[1].y;
34 printf("%d", SPFA(0));
35 }
36 bool legal(int Ax, int Bx, int Ay, int By)
37 {
38 if((Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) <= r * r)
39 return true;
40 else
41 return false;
42 }
43 int SPFA(int i)
44 {
45 queue<node> s;
46 node p;// s.x = Sx;// s.y = Sy;// s.push(map[0]);
47 p.x = Sx;
48 p.y = Sy;
49 s.push(p);
50 while(!s.empty())
51 {
52 p = s.front();
53 s.pop();
54 for(int i = 1; i < n + m; i ++)
55 {
56 if(legal(p.x, map[i].x, p.y, map[i].y))
57 {
58 if(p.x == map[i].x && p.y == map[i].y)
59 continue;
60 if(map[i].x == Tx && map[i].y == Ty)
61 return p.step;
62 map[i].kcount = p.kcount;
63 // if(map[i].x == 4 && map[i].y == 0)
64 // printf("_%d %d_\n", map[i].kcount, map[i].step);//输出2,对的,但是后面变1了
65 // printf("_%d %d_\n", map[2].kcount, map[2].step);
66 if(i >= n)
67 {
68 if(p.kcount == k)//问题1,还有就是每一个的线路要赋值p.kcount
69 continue;
70 map[i].kcount = p.kcount + 1;
71 }
72 // if(map[i].step > p.step + 1)//这样写进行不下去,visit又死锁
73 map[i].step = p.step + 1;// printf("%d\n", map[i].step);
74 s.push(map[i]);
75 }
76 }
77 }
78 return 0;
79 }
80 //5 3 1 3
81 //0 0
82 //5 5
83 //0 3
84 //0 5
85 //3 5
86 //3 3
87 //4 4
88 //3 0
89
90 //10 4 2 1
91 //0 0
92 //5 0
93 //0 1
94 //0 2
95 //0 3
96 //1 3
97 //3 0
98 //3 1
99 //3 2
100 //3 3
101 //1 0
102 //2 0
103 //2 3
104 //4 0


纠结:为什么acm大佬说代码思路错了重写比较好,原有思路上改进不是更厉害么

太糟糕了,那个step有问题,是上一个,所以打算重写

中途还越界了,因为我是想跳过起始点不用再压入队列,所以就for没从0开始,后面dec_都是INT_MAX所以+1就崩了。(哎。。比较混乱,我也不知道当时为什么这么写的了。就是82行那个。。。。)

这里的dec_,我试了一下dec作为数组是没有问题的,但是这里的AC代码,将dec_改为dec是会报错的。很奇怪。

C:\Users\GerJCS岛\Desktop\CCF.cpp|28|error: reference to 'dec' is ambiguous

【原因和解决方法】

一般是由于定义的xx变量名称与库函数中的函数名xx有重名现象,通常做法是将定义的变量的首字母大写就不会重名了。

int函数最后要return 0;不然会报错

warning: control reaches end of non-void function [-Wreturn-type

之前错误思路用到了 点 是否在矩形内部

方法一:大的x赋给max_x,小的......,最后判断在范围之内即可。

方法二:没看懂

本题的两点距离不超过r

距离公式,直接平方;

坐标轴的两点就是,差的绝对值

还有一个什么判断点是否在圆内?不管了,这里用不到,先不考虑

  1 #include<cstdio>
2 #include<climits>
3 #include<cstring>
4 #include<queue>
5 #include <iostream>
6 #include <algorithm>
7 using namespace std;
8 //int map[205][2];
9 struct node
10 {
11 int x;
12 int y;
13 // int step;
14 int kcount;//其实应该重写的,这里我没有续写是感觉浪费时间没必要,且这里的kcount应该是变量的不应该是成员变量。
15 } map[205];
16 int n, m, k, r;
17 int Sx, Sy;
18 int Tx, Ty;
19 int SPFA(int i);
20 bool legal(int Ax, int Bx, int Ay, int By);
21 int dec_[205][105];//居然C:\Users\GerJCS岛\Desktop\CCF.cpp|27|error: reference to 'dec' is ambiguous|
22 int main()
23 {
24 scanf("%d %d %d %d", &n, &m, &k, &r);
25 for(int i = 0; i < n + m; i ++)
26 {
27 scanf("%d %d", &map[i].x, &map[i].y);
28 // map[i].step = INT_MAX;
29 map[i].kcount = 0;
30 }
31 // for(int i = 0; i < n + m; i ++)
32 // for(int j = 0; j < m; j ++)
33 for(int i = 0; i < 201; i ++)
34 for(int j = 0; j < 101; j ++)
35 dec_[i][j] = INT_MAX;
36 dec_[0][0] = 0;
37
38 // map[0].step = 0;
39 Sx = map[0].x;
40 Sy = map[0].y;
41 Tx = map[1].x;
42 Ty = map[1].y;
43 printf("%d\n", SPFA(0));
44 printf("%d %d\n", dec_[6][2], dec_[6][1]);
45 }
46 bool legal(int Ax, int Bx, int Ay, int By)
47 {
48 if((Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) <= r * r)
49 return true;
50 else
51 return false;
52 }
53 int SPFA(int i)
54 {
55 queue<node> s;
56 node p;// s.x = Sx;// s.y = Sy;// s.push(map[0]);
57 p.x = Sx;
58 p.y = Sy;
59 s.push(p);
60 while(!s.empty())
61 {
62 p = s.front();
63 s.pop();
64 for(int i = 0; i < n + m; i ++)
65 {
66 if(legal(p.x, map[i].x, p.y, map[i].y))
67 {
68 if(p.x == map[i].x && p.y == map[i].y)
69 continue;
70 if(map[i].x == Tx && map[i].y == Ty)
71 return dec_[1][p.kcount];
72 map[i].kcount = p.kcount;
73 // if(map[i].x == 4 && map[i].y == 0)
74 // printf("_%d %d_\n", map[i].kcount, map[i].step);//输出2,对的,但是后面变1了
75 // printf("_%d %d_\n", map[2].kcount, map[2].step);
76 if(i >= n)
77 {
78 if(p.kcount == k)//问题1,还有就是每一个的线路要赋值p.kcount
79 continue;
80 map[i].kcount = p.kcount + 1;
81 }
82 if(dec_[i][map[i].kcount] > dec_[i][p.kcount] + 1){//这样写进行不下去,visit又死锁
83 printf("TEST %d\n", dec_[0][0]);
84 printf("$$%d %d$\n", dec_[i][map[i].kcount], dec_[i][p.kcount] );//卧槽,越界了
85 dec_[i][map[i].kcount] = dec_[i][p.kcount] + 1;//这样写进行不下去,visit又死锁
86 // map[i].step = p.step + 1;// printf("%d\n", map[i].step);
87 s.push(map[i]);
88 }
89 }
90 }
91 }
92 return 0;
93 }
94 ////5 3 1 3
95 ////0 0
96 ////5 5
97 ////0 3
98 ////0 5
99 ////3 5
100 ////3 3
101 ////4 4
102 ////3 0
103 //
104 ////10 4 2 1
105 ////0 0
106 ////5 0
107 ////0 1
108 ////0 2
109 ////0 3
110 ////1 3
111 ////3 0
112 ////3 1
113 ////3 2
114 ////3 3
115 ////1 0
116 ////2 0
117 ////2 3
118 ////4 0
119
120 //
121 //#include <iostream>
122 //#include <algorithm>
123 //#include <queue>
124 //#define INF 0x7f7f7f7f
125 //
126 //using namespace std;
127 //
128 //struct point
129 //{
130 // long long x;
131 // long long y;
132 //} p[201];
133 //struct node
134 //{
135 // int i; //表示到达的路由器 i
136 // int k; //表示 k 个增设路由器
137 //};
138 //int d[201][201]; //用d[i][k]表示从起点到达i的最短路径,经过了k个增设路由器
139 //bool vis[201][201];//入队标志 ,用vis[i][k] i表示节点,k表示新增节点个数
140 //bool map[201][201]; //图矩阵
141 //
142 ////spfa 算法
143 //int spfa(int n, int m, int k)
144 //{
145 // queue<node> q;
146 // for(int i = 0; i < 201; i++) //初始化 vis,d
147 // {
148 // for(int j = 0; j < 201; j++)
149 // {
150 // vis[i][j] = 0;//未入队
151 // d[i][j] = INF;//路径无穷大
152 // }
153 // }
154 // node front, tem;
155 // front.i = 0;//源点是 0
156 // front.k = 0;//增点也是 0个
157 // d[front.i][front.k] = 0; //
158 // q.push(front);
159 // while(!q.empty())
160 // {
161 // front = q.front();
162 // q.pop();
163 // vis[front.i][front.k] = 0;//出队
164 // for(int i = 0; i < n + m; i++)
165 // {
166 // if(map[front.i][i]) //如果从front.x 到 i 有路径
167 // {
168 // tem.i = i;
169 // tem.k = front.k;
170 // if(i >= n)
171 // tem.k++;
172 // if(tem.k <= k && d[tem.i][tem.k] > d[front.i][front.k] + 1)//我觉得这里不用判断大小吧?????对于后可以,对于本局也可以????????????????????????
173 // {
174 // if(tem.i == 6)
175 // printf("-%d %d-\n", d[tem.i][tem.k], d[front.i][front.k]);
176 //
177 // d[tem.i][tem.k] = d[front.i][front.k] + 1;
178 //
179 // if(tem.i == 6)
180 // printf("……%d %d\n", d[tem.i][tem.k], d[front.i][front.k]);
181 //
182 // if(vis[tem.i][tem.k] == 0)
183 // {
184 // q.push(tem);
185 // vis[tem.i][tem.k] = 1;
186 // }
187 // }
188 // }
189 // }
190 // }
191 // int ans = INF;
192 // for(int i = 0; i <= k; i++)
193 // {
194 // ans = min(ans, d[1][i]);
195 // //cout<<d[1][i]<<" ";
196 // }
197 // return ans;
198 //}
199 //
200 //
201 //
202 //int main()
203 //{
204 //// printf("%d", INF);
205 //// 2139062143
206 // int n, m, k;
207 // long long r;
208 // cin >> n >> m >> k >> r;
209 // for(int i = 0; i < n + m; i++)
210 // {
211 // cin >> p[i].x >> p[i].y;
212 // }
213 // for(int i = 0; i < n + m; i++) //构建图
214 // {
215 // for(int j = i + 1; j < n + m; j++)
216 // {
217 // if((p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y) <= r * r)
218 // {
219 // map[i][j] = 1;
220 // map[j][i] = 1;
221 // }
222 // }
223 // }
224 // int ans = spfa(n, m, k);
225 // cout << ans - 1;
226 // return 0;
227 //}

我做后参考了 题解 才懂的,写的非常好。我是最开始查很多题解都是要设置二维数组,但是死活不理解什么意思,通过自己写了好几次错误代码找出问题所在,才明白为什么要用二维数组存储一个 k 一个 i ,最后翻到这个题解再结合上面链接里的SPFA讲解才懂,最后AC。

最后A掉了

我改了两次,重点80行:

if(dec_[i][mid_k] > dec_[willpush.i][willpush.k] + 1)

i 对应willpush.i

mid_k对应willpush.k

即 都是这一次的  都是轴点的 作比较。有点像hdoj的走楼梯,好像也有点像动态规划的表达式,还像那个递推公式。

这是这道题的巧妙所在,也是精髓,SPFA的精髓。

if(dec_[i][mid_k] > dec_[willpush.i][willpush.k] + 1)
 
  1 //再一次提交
2 //https://paste.ubuntu.com/p/XjYJ6dVXBV/
3 //80分
4
5 //小问题,大错误.d对队列和BFS/SPFA思路不清晰
6 //https://paste.ubuntu.com/p/bsRzbhq5Z4/
7
8
9 #include<cstdio>
10 #include<climits>
11 #include<cstring>
12 #include<queue>
13 #include <iostream>
14 #include <algorithm>
15 using namespace std;
16 struct node
17 {
18 int x;
19 int y;
20 int i;
21 int k;
22 }map[205];
23 int n, m, k;
24 long long int r;
25 int Sx, Sy;
26 int Tx, Ty;
27 int SPFA(int i);
28 bool legal(long long int Ax, long long int Bx, long long int Ay, long long int By);
29 int dec_[205][105];
30 int main()
31 {
32 scanf("%d %d %d %lld", &n, &m, &k, &r);
33 for(int i = 0; i < n + m; i ++)
34 scanf("%d %d", &map[i].x, &map[i].y);
35 for(int i = 0; i < 201; i ++)
36 for(int j = 0; j < 101; j ++)
37 dec_[i][j] = INT_MAX - 10;
38 dec_[0][0] = 0;
39 Sx = map[0].x;
40 Sy = map[0].y;
41 Tx = map[1].x;
42 Ty = map[1].y;
43 printf("%d\n", SPFA(0));
44 }
45 bool legal(long long int Ax, long long int Bx, long long int Ay, long long int By)
46 {
47 if((Ax - Bx) * (Ax - Bx) + (Ay - By) * (Ay - By) <= r * r)
48 return true;
49 else
50 return false;
51 }
52 int SPFA(int i)
53 {
54 queue<node> s;
55 node mid;//中转
56 node willpush;//即将压入
57 node next;
58 mid.x = Sx;
59 mid.y = Sy;
60 mid.i = 0;
61 mid.k = 0;
62 s.push(mid);
63 int mid_k;
64 while(!s.empty()){
65 willpush = s.front();
66 s.pop();
67 for(int i = 0; i < n + m; i ++){
68 if(legal(willpush.x, map[i].x, willpush.y, map[i].y))
69 {
70 if(willpush.x == map[i].x && willpush.y == map[i].y)
71 continue;
72 if(map[i].x == Tx && map[i].y == Ty)
73 return dec_[willpush.i][willpush.k];//这些个坐标,变量很有讲究
74 mid_k = willpush.k;
75 if(i >= n){
76 if(willpush.k == k)
77 continue;
78 mid_k = willpush.k + 1;
79 }
80 if(dec_[i][mid_k] > dec_[willpush.i][willpush.k] + 1){
81 dec_[i][mid_k] = dec_[willpush.i][willpush.k] + 1;
82 next.x = map[i].x;
83 next.y = map[i].y;//调试好久。。。。
84 next.i = i;
85 next.k = mid_k;
86 s.push(next);
87 }
88 }
89 }
90 }
91 return 0;
92 }
93
94 //5 3 1 3
95 //0 0
96 //5 5
97 //0 3
98 //0 5
99 //3 5
100 //3 3
101 //4 4
102 //3 0
103
104 //10 4 2 1
105 //0 0
106 //5 0
107 //0 1
108 //0 2
109 //0 3
110 //1 3
111 //3 0
112 //3 1
113 //3 2
114 //3 3
115 //1 0
116 //2 0
117 //2 3
118 //4 0
119
120
121 //最后满分

PS:所有的BFS接法都有点不可通过。所有的visit都可以去掉

我真的很疑惑为什么这么多人(看着应该是个大佬啊),却都用BFS来做。。。。可能刚刷不太了解细节,再刷刷感悟一下再回头来看这个题目吧

更多题解(我参考了很多题解才看明白的,因为可能有些描述不是很能立刻理解)
https://blog.csdn.net/qq_32445015/article/details/79796830

另一种思路,没看懂

好烦,我不习惯看别人代码,这个代码纯bfs,为什么能满分。(而且还有人看懂了,做出了评论指正,哎)

完全看不懂。。。

又是在拖延,难道工作都是要这么看代码的吗?那些只会C语言跨考HIT,科软的朋友两年能看会代码了么

强迫症思维快疯了。。。大佬们都是迅速写,迅速交流(或者网上迅速看懂题解),如果BFS错误思路AC了再看更多题解就能立马反应过来错在哪里。而我掰不开镊子一样,嬷嬷丢,来回转圈圈,就算正解SPFA AC了,最后看BFS还是看不懂。也不愿意回顾,强迫写题解。。。可能这就是为什么考2次都。。。。。。逃避和不想复习吧。。。很痛苦。。。这个时候了还魔怔一样刷CCF,哪怕刷,别人也是PAT,哎。。。。

哎,像一个死废物一样,陷入一个怪圈循环。。。黑暗之海。。。我这么弱还活在世界上,真的对不起。。想要做出改变。。。

CCF 无线网络的更多相关文章

  1. CCF CSP 201403-4 无线网络

    CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201403-4 无线网络 问题描述 目前在一个很大的平面房间里有 n 个无线路由器,每个无线路 ...

  2. CCF模拟 无线网络

    无线网络 时间限制: 1.0s 内存限制: 256.0MB   问题描述 目前在一个很大的平面房间里有 n 个无线路由器,每个无线路由器都固定在某个点上.任何两个无线路由器只要距离不超过 r 就能互相 ...

  3. NOIP2014无线网络发射器选址改编1

    问题描述 随着智能手机的日益普及,人们对无线网的需求日益增大.某城市决定对城市内的公共场所覆盖无线网. 假设该城市的布局为由严格平行的129条东西向街道和129条南北向街道所形成的网格状,并且相邻的平 ...

  4. win10系统下连接无线网络掉线问题解决办法

    打开驱动精灵----系统诊断 找一个可修复的驱动点击 选择连不上网中的查看更多 有连不上网络,网络连接受限,解决无线间歇性掉网问题 进入计算机管理----设备管理 修改无线网络属性(名称含有wirel ...

  5. PDA移动POS终端系统,实现专柜或店铺的收货、零售、盘点通过无线网络直接连接总部中央数据库,实现高效安全的移动供应链管理

    利用PDA移动终端,实现专柜或店铺的收货.零售.盘点等一体化操作,通过无线网络直接连接总部中央数据库,实现高效安全的移动供应链管理. · PDA订货会应用解决方案利用PDA或电脑系统,在订货会现场直接 ...

  6. linux 下链接无线网络

    无线网卡配置此页由Linux Wiki用户Chenxing于2008年11月27日 (星期四) 09:28的最后更改. 在1233456的工作基础上.本文介绍在Linux命令行界面中手动配置无线网卡的 ...

  7. 卓越精Forsk.Atoll.v3.3.2.10366无线网络

    卓越精Forsk.Atoll.v3.3.2.10366无线网络 Atoll是法国 FORSK 公司开发的,是一个全面的.基于Windows的.支持2G.3G.4G多种技术,用户界面 友好的无线网络规划 ...

  8. CentOS 7 最小化安装的无线网络配置

    1.首先下载iw工具. yum -y install iw 2.获取无线网卡的名称 执行iw dev,假设获得名称为 wlp3s0(示例) 3.激活无线网络接口 执行ip link set wlp3s ...

  9. CentOS 7如何连接无线网络

    虽然查阅了相关网络资料,但是以下内容均为原创内容,只有干货,无废话. 1.切换到超级用户 [Oscar@localhost 桌面]$ su root 2.查询可用的无线网卡,其中红色为网卡号 [Osc ...

  10. 双系统下(Ubuntu + win7)windows 无法连接无线网络

    双系统下(Ubuntu + win7)windows 无法连接无线网络 今天开机登录win7,突然发现无法使用无线网络(WiFi信号标志有个大红叉),于是查看设备驱动,一切正常,这就奇怪了:用Wind ...

随机推荐

  1. windows隐藏文件如何查看

    1.组织 2.查看 3.显示隐藏文件

  2. 赛博斗地主——使用大语言模型扮演Agent智能体玩牌类游戏。

    通过大模型来实现多个智能体进行游戏对局这个想对已经比较成熟了无论是去年惊艳的斯坦福小镇还是比如metaGPT或者类似的框架都是使用智能体技术让大模型来操控,从而让大模型跳出自身"预测下一个t ...

  3. LeetCode 295. Find Median from Data Stream数据流的中位数 (C++/Java)

    题目: Median is the middle value in an ordered integer list. If the size of the list is even, there is ...

  4. docker registry 镜像源

    修改文件 /etc/docker/daemon.json vi /etc/docker/daemon.json添加以下内容后,重启docker服务: { "registry-mirrors& ...

  5. Prometheus + Grafana (2) mysql、redis、Docker容器、服务端点以及预警

    接着上一节 <Prometheus + Grafana (1) 监控 >,我们继续探讨 Prometheus + Grafana 的复杂应用 实现目标 这节我们的目标是搭建一个多维度监控微 ...

  6. Python3.7+Robot Framework+RIDE1.7.4.1安装使用教程

    一.解惑:Robot Framewprk今天我们聊一聊,Robot Framework被众多测试工程师误会多年的秘密.今天我们一起来揭秘一下,最近经常在各大群里听到许多同行,在拿Robot Frame ...

  7. github fork后对上游仓库的做rebase

    想对上游仓库做更新同步 先添加上游仓库 git remote add upstream https://github.com/原始作者/原始仓库.git 其中这里的upstream 是一个命名,和 o ...

  8. MySql 表数据的增、删、改、查

    数据表的增.删.改.查 前言 在学习 MySql 一定少不了对数据表的增.删.改.查,下面将详细讲解如何操作数据表. 前面已经建好了表 customer 列表如下: 插入数据 插入数据可以使用 INS ...

  9. restful接口返回JSONObject和父类抽象实现类设计,请求头获取sign和支付宝RSA签名验签工具类方法

    restful接口返回JSONObject和父类抽象实现类设计,请求头获取sign和支付宝RSA签名验签工具类方法 1.JSONObject可以通用数据的灵活性,类似Map数据,数据字段不清晰.具体返 ...

  10. 关于编译告警 C4819 的完整解决方案 - The file contains a character that cannot be represented in the current code page (number). Save the file in Unicode format to prevent data loss.

    引言 今天迁移开发环境的时候遇到一个问题,同样的操作系统和 Visual Studio 版本,原始开发环境一切正常,但是迁移后 VS 出现了 C4819 告警,上网查了中文的一些博客,大部分涵盖几种解 ...