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
对拍生成样例数据
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 }
###:
对拍代码,油田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 }
再整个bf.cpp(也就是网上的AC代码),再整个test.cpp(就是自己WA的代码),再整个run.bat(油田问题博客里有)
###:memset赋值为1问题
###:C语言命名规则不可以出现‘@’
###:这个题好像跟双端队列没关系,先不回顾双端队列了