Fork me on GitHub

HDU2612-Find a way

继续刷邝斌飞搜索专题

HDU2612 (hdoj专属)

 

思路:

Y出发BFS扫一遍,记录下到每个KFC的最少用时

M出发BFS扫一遍,记录下到每个KFC的最少用时

BFS正常找到就退,这里找够所有KFC再退

最后比较Y到每个KFC的最少步数与M到每个对应KFC最少步数之和,输出最小值

20min写完WA了

博客,发现YM也可以走,发现数据

3 3
YM@
###
###

输出就不对,改后依旧WA

改后代码:

  1 #include<stdio.h>
  2 #include<iostream>
  3 #include<queue>
  4 #include<string.h>
  5 using namespace std;
  6 char map[200][200];
  7 int Y_to_KFC[200][200];//记录Y去坐标为(x,y)的KFC店最少需要几步
  8 int M_to_KFC[200][200];
  9 
 10 int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
 11 struct Node{
 12     int x;
 13     int y;
 14     int step;
 15 };
 16 queue<Node>q;
 17 
 18 int vis[200][200];
 19 Node node;
 20 
 21 struct Node_For_shift2{//Node_For_@_好像不可以,这样命名简单明了,防止看到个变量回忆半天这是啥变量回忆半天
 22     int x;
 23     int y;
 24 };
 25 Node_For_shift2 node_shift2[400];
 26 int main()
 27 {
 28     int n,m;
 29     int Y_x,Y_y;
 30     int M_x,M_y;
 31     while(cin>>n>>m){
 32         int the_sum_of_KFC=0;
 33         int the_sum_of_KFC_that_Y_find=0;//给下面搜索用到,Y搜到了几个KFC,如果搜到的是sum就别搜了
 34         int the_sum_of_KFC_that_M_find=0;
 35         getchar();
 36         memset(vis,0,sizeof(vis));
 37         memset(Y_to_KFC,0,sizeof(Y_to_KFC));
 38         memset(M_to_KFC,0,sizeof(M_to_KFC));
 39         for(int i=0;i<n;i++){
 40             for(int j=0;j<m;j++){
 41                 scanf("%c",&map[i][j]);
 42                 if(map[i][j]=='Y'){
 43                     Y_x=i;
 44                     Y_y=j;
 45                 }
 46                 if(map[i][j]=='M'){
 47                     M_x=i;
 48                     M_y=j;
 49                 }
 50                 if(map[i][j]=='@'){
 51                     the_sum_of_KFC++;
 52                     node_shift2[the_sum_of_KFC].x=i;
 53                     node_shift2[the_sum_of_KFC].y=j;
 54                 }
 55             }
 56             getchar();
 57         }
 58 
 59 //        难道用什么双端队列?先用两次队列写个
 60 //        第一次找Y去所有KFC的最少步骤
 61         node.x=Y_x;
 62         node.y=Y_y;
 63         node.step=0;
 64         q.push(node);
 65         vis[node.x][node.y]=1;
 66         while(!q.empty()){
 67             Node thisnode=q.front();
 68             Node nextnode;
 69             q.pop();
 70 
 71             if(map[thisnode.x][thisnode.y]=='@'){
 72                 Y_to_KFC[thisnode.x][thisnode.y]=thisnode.step;
 73                 the_sum_of_KFC_that_Y_find++;//代表找到了一个KFC
 74                 if(the_sum_of_KFC_that_Y_find==the_sum_of_KFC)//如果都找到了还搜个JB直接退了,没找全就继续找,继续搜tmd
 75                 {
 76                     while(!q.empty())//清空队列,不仅下一组数据要用,d待会M BFS也要用
 77                         q.pop();
 78                     break;
 79 
 80                 }
 81             }
 82 
 83             for(int i=0;i<4;i++){
 84                 if(0<=thisnode.x+dir[i][0]&&thisnode.x+dir[i][0]<n
 85                    &&0<=thisnode.y+dir[i][1]&&thisnode.y+dir[i][1]<m
 86                    &&vis[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]==0
 87                    &&((map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='.')
 88                    || (map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='@')
 89                       || ((map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='M')) )){//妈的,if写的太长最后忘记加这个大括号了,调试找仨小时
 90                 nextnode.x=thisnode.x+dir[i][0];
 91                 nextnode.y=thisnode.y+dir[i][1];
 92                 nextnode.step=thisnode.step+1;
 93                 q.push(nextnode);
 94                 vis[nextnode.x][nextnode.y]=1;
 95                    }
 96             }
 97         }
 98 
 99         memset(vis,0,sizeof(vis));
100 //        第二次找M去所有KFC的最少步骤
101         node.x=M_x;
102         node.y=M_y;
103         node.step=0;
104         q.push(node);
105         while(!q.empty()){
106             Node thisnode=q.front();
107             Node nextnode;
108             q.pop();
109 
110             if(map[thisnode.x][thisnode.y]=='@'){
111                 M_to_KFC[thisnode.x][thisnode.y]=thisnode.step;
112                 the_sum_of_KFC_that_M_find++;//代表找到了一个KFC
113                 if(the_sum_of_KFC_that_M_find==the_sum_of_KFC)//如果都找到了还搜个JB直接退了,没找全就继续找,继续搜tmd
114                 {
115                     while(!q.empty())//清空队列,不仅下一组数据要用,d待会M BFS也要用
116                         q.pop();
117                     break;
118                 }
119             }
120 
121 
122             for(int i=0;i<4;i++){
123                 if(0<=thisnode.x+dir[i][0]&&thisnode.x+dir[i][0]<n
124                    &&0<=thisnode.y+dir[i][1]&&thisnode.y+dir[i][1]<m
125                    &&vis[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]==0
126                    &&((map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='.')
127                    || (map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='@')
128                       || (map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='Y'))){
129                 nextnode.x=thisnode.x+dir[i][0];
130                 nextnode.y=thisnode.y+dir[i][1];
131                 nextnode.step=thisnode.step+1;
132                 q.push(nextnode);
133                 vis[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=1;
134                    }
135             }
136         }
137 
138 //        至此得到了两个数组,开始比较Y_to_KFC + M_to_KFC的最小值
139         int min=800;//总共才Y走一个200*200,M走一个200*200
140         for(int i=1;i<=the_sum_of_KFC;i++)
141             if(Y_to_KFC[node_shift2[i].x][node_shift2[i].y]
142                + M_to_KFC[node_shift2[i].x][node_shift2[i].y]<min)//以后再也不看别人代码了,md我发现自己写的代码,写的时候缺啥少啥现用现去定义,命名完比如这一行,我写的时候现在很清晰,但你让我一个月后再来看这段,就很混乱,理解"别人或之前自己写的"代码比自己写代码难多了,释怀
143             {
144                 min=Y_to_KFC[node_shift2[i].x][node_shift2[i].y]
145                 + M_to_KFC[node_shift2[i].x][node_shift2[i].y];
146             }
147         cout<<min*11<<endl;
148     }
149 }

我看好多人TLE了,我是还没到这步呢还是咋的,BFS怎么可能TLE,我WA在哪了

不知道都是copy的代码还是咋的,那些TLE的为啥都是先找KFC然后反向找Y和M

傻吊一群,自作聪明,那样100个KFC你得搜100次,我这Y/M出发搜一遍就全出来了

正打算对拍呢,发现25行开了400,笔误,200*200是40000

139行定义的最大值800,应该是80000

艹了,改完还是WA

1 可忽略###############################################################################################3#####################回忆,西安算竞培训,毛老师W茂G:镜子十八岁的混乱私生活,王茂广,你们有问题可以问题,正常中午休息的然而我并..并不休息。西安助理,肛塞,培训结束一起走,快速进入自己思考状态门口看题(值得学习,而我做不到这一点,总是被旁边女生无法专注,lu都无法专注,你家里不是做生意的吧,你长的像研究生)。“‘被初级班问住了’”,灯泡问题,抽烟,事业公司,电话你们去玩吧。赵婧怡好友生clj殖隔离,景若云景学姐栗子。吹乐器责任推给室友,知乎人不错。AA梁芝麻感恩。岛娘/左神/邓思雨现场WA,邓思雨还在考研,工程项目圆里题目,很苦逼就别搞了,14天批量生产铜牌,ktv古典声乐嚎叫。西工大姜学峰教练没有我搞不到的题,v8.艾教。高级问不明白的基础,初级问高深的的zhuang。指点美赛,澳洲悉尼大学辅导数据结构计组,编译原理。岛娘Q空间邀请打CF,q神2次给链接金牌,q神/岛娘被拉黑.又黑又硬,今天我高兴不然我就骂你了哈哈哈。毛毛雨:我不用VS因为比赛不用哈哈,有点弱。赞同那开发“自学的不知道基础”,法“年龄大才好”,“写那么多一看就是培训班的,正经上班哪有时间学那么多”。碱水,凝紫暮see youin bupt。小说曾经称霸江湖如今武功散尽。贵灿:我看你百度网盘都心疼你。回忆虹HIT复试呵呵那个问题,都原题,达摩院想去就去导师推荐,回忆bupt复试他们说的,回忆二哥保研的问题简直一言难尽心有不甘,帮二哥保研,帮HIT虹/buptLXT机试各种。大厂卡学历。农发行那个snow开发哈工程垃圾研究生,却被视为呵呵。总行光宗耀祖。呵呵,而我只有失败人生。都用最简单的方式完成了,走上人生巅峰,(那些非hit非bupt的研究生垃圾提都不想提),你跌跌撞撞从没做成什么,总是选择最困难的,一场空,一无是处穷途末路可有可无,好想找人来操我却找不到人,岛娘,傻逼废物垃圾废人###############################################################################
2  
View Code

 

对拍生成样例数据

18 4
@#@*
@@##
*@*@
@#@#
@@*@
@*@@
@@#*
@@**
@##@
####
#@@#
*#Y*
##@#
#*@#
#*@@
***M
#@*@
@**@

网上别人的AC代码输出55

我的代码输出0

简化样例:

6 4
*#Y*
##@#
#*@#
#*@@
***M
#@*@

艹,发现地图整错了,是'.'不是'*'

但为啥AC代码还能输出正确的(疑点搁置一)

如果全是#,我代码输出0,AC代码输出负数(疑点搁置二)

AC代码ctrlZ不结束(疑点搁置三)

 

修改data.cpp地图后重新生成的样例

13 7
..#.@.Y
@#.@.@@
@@#@.@@
#@@.@..
.@@@@.M
####@.#
@@#...@
.#.@@#.
.#@@@@.
##.#.@.
.@###.@
@#@.@@#
...@@..

我代码又输出了0

AC代码是44 

 

想了下找到问题了,比较的时候先定义了最大值,遇到最小的就会min更新,但会有个问题,比如三个KFC店,第三个才是答案,但在走第一个的时候,如果Y/M都到不了,那存储的就是初始值0了,此时min更新为0,那无论后面到达KFC的路径怎样小都无法再更新最小值min了。所以先把Y_to_KFC和M_to_KFC初始化为最大,找不到就是最大值,此时利用memset赋值十六进制什么的,memset为1,其实就很大了试试。立马AC

AC代码

  1 #include<stdio.h>
  2 #include<iostream>
  3 #include<queue>
  4 #include<string.h>
  5 using namespace std;
  6 char map[200][200];
  7 int Y_to_KFC[200][200];//记录Y去坐标为(x,y)的KFC店最少需要几步
  8 int M_to_KFC[200][200];
  9 
 10 int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
 11 struct Node{
 12     int x;
 13     int y;
 14     int step;
 15 };
 16 queue<Node>q;
 17 
 18 int vis[200][200];
 19 Node node;
 20 
 21 struct Node_For_shift2{//Node_For_@_好像不可以,这样命名简单明了,防止看到个变量回忆半天这是啥变量回忆半天
 22     int x;
 23     int y;
 24 };
 25 Node_For_shift2 node_shift2[400];
 26 int main()
 27 {
 28     int n,m;
 29     int Y_x,Y_y;
 30     int M_x,M_y;
 31     while(cin>>n>>m){
 32         int the_sum_of_KFC=0;
 33         int the_sum_of_KFC_that_Y_find=0;//给下面搜索用到,Y搜到了几个KFC,如果搜到的是sum就别搜了
 34         int the_sum_of_KFC_that_M_find=0;
 35         getchar();
 36         memset(vis,0,sizeof(vis));
 37         memset(Y_to_KFC,1,sizeof(Y_to_KFC));
 38         memset(M_to_KFC,1,sizeof(M_to_KFC));
 39         for(int i=0;i<n;i++){
 40             for(int j=0;j<m;j++){
 41                 scanf("%c",&map[i][j]);
 42                 if(map[i][j]=='Y'){
 43                     Y_x=i;
 44                     Y_y=j;
 45                 }
 46                 if(map[i][j]=='M'){
 47                     M_x=i;
 48                     M_y=j;
 49                 }
 50                 if(map[i][j]=='@'){
 51                     the_sum_of_KFC++;
 52                     node_shift2[the_sum_of_KFC].x=i;
 53                     node_shift2[the_sum_of_KFC].y=j;
 54                 }
 55             }
 56             getchar();
 57         }
 58 
 59 //        难道用什么双端队列?先用两次队列写个
 60 //        第1次找Y去所有KFC的最少步骤
 61         node.x=Y_x;
 62         node.y=Y_y;
 63         node.step=0;
 64         q.push(node);
 65         vis[node.x][node.y]=1;
 66         while(!q.empty()){
 67             Node thisnode=q.front();
 68             Node nextnode;
 69             q.pop();
 70 
 71             if(map[thisnode.x][thisnode.y]=='@'){
 72                 Y_to_KFC[thisnode.x][thisnode.y]=thisnode.step;
 73                 the_sum_of_KFC_that_Y_find++;//代表找到了一个KFC
 74                 if(the_sum_of_KFC_that_Y_find==the_sum_of_KFC)//如果都找到了还搜个JB直接退了,没找全就继续找,继续搜tmd
 75                 {
 76                     while(!q.empty())//清空队列,不仅下一组数据要用,d待会M BFS也要用
 77                         q.pop();
 78                     break;
 79 
 80                 }
 81             }
 82 
 83             for(int i=0;i<4;i++){
 84                 if(0<=thisnode.x+dir[i][0]&&thisnode.x+dir[i][0]<n
 85                    &&0<=thisnode.y+dir[i][1]&&thisnode.y+dir[i][1]<m
 86                    &&vis[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]==0
 87                    &&((map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='.')
 88                    || (map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='@')
 89                       || (map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='M'))){//妈的,if写的太长最后忘记加这个大括号了,调试找仨小时
 90                 nextnode.x=thisnode.x+dir[i][0];
 91                 nextnode.y=thisnode.y+dir[i][1];
 92                 nextnode.step=thisnode.step+1;
 93                 q.push(nextnode);
 94                 vis[nextnode.x][nextnode.y]=1;
 95                    }
 96             }
 97         }
 98 
 99         memset(vis,0,sizeof(vis));
100 //        第2次找M去所有KFC的最少步骤
101         node.x=M_x;
102         node.y=M_y;
103         node.step=0;
104         q.push(node);
105         while(!q.empty()){
106             Node thisnode=q.front();
107             Node nextnode;
108             q.pop();
109 
110             if(map[thisnode.x][thisnode.y]=='@'){
111                 M_to_KFC[thisnode.x][thisnode.y]=thisnode.step;
112                 the_sum_of_KFC_that_M_find++;//代表找到了一个KFC
113                 if(the_sum_of_KFC_that_M_find==the_sum_of_KFC)//如果都找到了还搜个JB直接退了,没找全就继续找,继续搜tmd
114                 {
115                     while(!q.empty())//清空队列,不仅下一组数据要用,d待会M BFS也要用
116                         q.pop();
117                     break;
118                 }
119             }
120 
121 
122             for(int i=0;i<4;i++){
123                 if(0<=thisnode.x+dir[i][0]&&thisnode.x+dir[i][0]<n
124                    &&0<=thisnode.y+dir[i][1]&&thisnode.y+dir[i][1]<m
125                    &&vis[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]==0
126                    &&((map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='.')
127                    || (map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='@')
128                       || (map[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=='Y'))){
129                 nextnode.x=thisnode.x+dir[i][0];
130                 nextnode.y=thisnode.y+dir[i][1];
131                 nextnode.step=thisnode.step+1;
132                 q.push(nextnode);
133                 vis[thisnode.x+dir[i][0]][thisnode.y+dir[i][1]]=1;
134                    }
135             }
136         }
137 
138 //        至此得到了两个数组,开始比较Y_to_KFC + M_to_KFC的最小值
139         int min=80000;//总共才Y走一个200*200,M走一个200*200
140         for(int i=1;i<=the_sum_of_KFC;i++)
141             if(Y_to_KFC[node_shift2[i].x][node_shift2[i].y]
142                + M_to_KFC[node_shift2[i].x][node_shift2[i].y]<min)//以后再也不看别人代码了,md我发现自己写的代码,写的时候缺啥少啥现用现去定义,命名完比如这一行,我写的时候现在很清晰,但你让我一个月后再来看这段,就很混乱,理解"别人或之前自己写的"代码比自己写代码难多了,释怀
143             {
144                 min=Y_to_KFC[node_shift2[i].x][node_shift2[i].y]
145                 + M_to_KFC[node_shift2[i].x][node_shift2[i].y];
146             }
147         cout<<min*11<<endl;
148     }
149 }

 

现在一个一个解决遇到的问题,

但为啥AC代码还能输出正确的(疑点搁置一):他用的是只要不是'#'就都进入队列

如果全是#,我代码输出0,AC代码输出负数(疑点搁置二):他用的是0x3f3f3f3f,乘11后就负数了,没啥好研究的,计组知识,浮点/补码反码啥的到时候再说

AC代码ctrlZ不结束(疑点搁置三):应该是我没运行对,其实是可以结束的

至此所有遇到的问题均已解决。

最后学习下这人博客里的代码,好清爽简洁

 

 

过程中遇到的其他坑和小知识

###:

关于if里“或”运算符加不加括号问题

 1 #include<stdio.h>
 2 int main()
 3 {
 4     if(false && (true || true)){
 5         printf("#\n");
 6     }
 7 
 8     if(false && true || true){//从前往后判断
 9         printf("$\n");
10     }
11 }
View Code

###:

对拍代码,油田oil问题的博客回顾了对拍,但那个题run.bat运行没反应,这个题突然好了

data.cpp代码(已更新为正确的)

 1 //#include<bits/stdc++.h>
 2 #include<stdio.h>
 3 #include<iostream>
 4 #include<time.h>
 5 using namespace std;
 6 char x[3]={'@','.','#'};
 7 char map[100][100];
 8 int main() {
 9     srand(time(0) + (unsigned long long)(new char));
10 
11     int n = rand() % 20;
12     int m = rand() % 20;
13 
14     int Yx = rand() % n;
15     int Yy = rand() % m;
16 
17     int Mx = rand() % n;
18     int My = rand() % m;
19     cout<<n<<" "<<m<<endl;
20     for(int i=0;i<n;i++){
21         for(int j=0;j<m;j++){
22             if(i==Yx&&j==Yy)
23                 cout<<'Y';
24             else if(i==Mx&&j==My)
25                 cout<<'M';
26             else{
27                 int num=rand() % 3;
28                 map[i][j]=x[num];
29                 cout<<map[i][j];
30             }
31         }
32         cout<<endl;
33     }
34 
35 }
View Code

再整个bf.cpp(也就是网上的AC代码),再整个test.cpp(就是自己WA的代码),再整个run.bat(油田问题博客里有)

###:memset赋值为1问题

###:C语言命名规则不可以出现‘@’

###:这个题好像跟双端队列没关系,先不回顾双端队列了

posted @ 2024-09-22 15:46  GerJCS  阅读(26)  评论(0)    收藏  举报