1 #include <iostream> 2 #include <deque> 3 #define N 256 4 using namespace std; 5 struct fruit //保存水果的坐标,数组的第1个元素的能量,用来记录水果的数目 6 { 7 int x; 8 int y; 9 int energy; //能量 10 int dis_toend; 11 int dis_tostart; 12 13 }fruits[18]; //记录水果的位置 14 15 struct node 16 { 17 int x; 18 int y; 19 int fru_num; //水果编号 20 int energy; //能量 21 }map[N][N]; 22 23 int dist[18][18]; //dist[i][j]表示第i个水果到第j个水果的距离 24 bool vis[N][N]; //记录脚印 25 int num; //水果数量 26 int m,n; //m行n列 27 deque<node> queue; //队列 28 29 30 int to_begin() //到起点的距离,保存在fruits_s;到终点的距离,保存在fruits_e。先起点,后终点。 31 { 32 queue.clear(); 33 memset(vis,0,sizeof(vis)); 34 queue.push_back(map[0][0]); //先入队列 35 vis[0][0]=1; //置为浏览过 36 37 int cor=map[0][0].energy; //起点开始能走的步数 38 int temp_num=0; //记录走了几步 39 int temp_n=0; //已发现的水果数量 40 41 while(queue.empty()==false && cor-- ) //队列不空,且无法够着其他水果。 42 { 43 int size=queue.size(); 44 for(int i=0; i<size; i++) //第temp_num步可达的,全部遍历一次 45 { 46 if(queue.front().energy>0) //此点有水果,保存距离 47 { 48 fruits[queue.front().fru_num].dis_tostart=temp_num; 49 if(num==++temp_n) return 0; //各水果均已搜过。每搜到一水果就进行判断 50 } 51 node temp=queue.front(); 52 queue.pop_front(); //出队 53 //将身边结点入队列,考虑四个方向 54 if(temp.x-1>=0 && map[temp.x-1][temp.y].energy>=0 && vis[temp.x-1][temp.y]==0) //同一行的,且未被访问过 55 { 56 vis[temp.x-1][temp.y]=1; //置为浏览过 57 queue.push_back( map[temp.x-1][temp.y] ); //入队列 58 } 59 if(temp.x+1<m && map[temp.x+1][temp.y].energy>=0 && vis[temp.x+1][temp.y]==0) //同一行的 60 { 61 vis[temp.x+1][temp.y]=1; 62 queue.push_back( map[temp.x+1][temp.y] ); 63 } 64 if(temp.y-1>=0 && map[temp.x][temp.y-1].energy>=0 && vis[temp.x][temp.y-1]==0) //同一列的 65 { 66 vis[temp.x][temp.y-1]=1; 67 queue.push_back( map[temp.x][temp.y-1] ); 68 } 69 if(temp.y+1<n && map[temp.x][temp.y+1].energy>=0 && vis[temp.x][temp.y+1]==0) //同一列的 70 { 71 vis[temp.x][temp.y+1]=1; 72 queue.push_back( map[temp.x][temp.y+1] ); 73 } 74 75 } 76 temp_num++; //步数 77 } 78 return 0; 79 } 80 81 82 int to_end() //到终点的距离 83 { 84 queue.clear(); 85 memset(vis,0,sizeof(vis)); 86 queue.push_back(map[m-1][n-1]); //先入队列 87 vis[m-1][n-1]=1; //置为浏览过 88 int temp_num=0; //记录走了几步 89 int temp_n=0; //已发现的水果数量 90 91 while(queue.empty()==false) //队列不空,且无法够着其他水果。 92 { 93 int size=queue.size(); 94 for(int i=0; i<size; i++) //第temp_num步可达的,全部遍历一次 95 { 96 if(queue.front().energy>0) //此点有水果,保存距离 97 { 98 fruits[queue.front().fru_num].dis_toend=temp_num; 99 if(num==++temp_n) return 0; //各水果均已搜过。每搜到一水果就进行判断 100 } 101 node temp=queue.front(); 102 queue.pop_front(); //出队 103 //将身边结点入队列,考虑四个方向 104 if(temp.x-1>=0 && map[temp.x-1][temp.y].energy>=0 && vis[temp.x-1][temp.y]==0) //同一行的,且未被访问过 105 { 106 vis[temp.x-1][temp.y]=1; //置为浏览过 107 queue.push_back( map[temp.x-1][temp.y] ); //入队列 108 } 109 if(temp.x+1<m && map[temp.x+1][temp.y].energy>=0 && vis[temp.x+1][temp.y]==0) //同一行的 110 { 111 vis[temp.x+1][temp.y]=1; 112 queue.push_back( map[temp.x+1][temp.y] ); 113 } 114 if(temp.y-1>=0 && map[temp.x][temp.y-1].energy>=0 && vis[temp.x][temp.y-1]==0) //同一列的 115 { 116 vis[temp.x][temp.y-1]=1; 117 queue.push_back( map[temp.x][temp.y-1] ); 118 } 119 if(temp.y+1<n && map[temp.x][temp.y+1].energy>=0 && vis[temp.x][temp.y+1]==0) //同一列的 120 { 121 vis[temp.x][temp.y+1]=1; 122 queue.push_back( map[temp.x][temp.y+1] ); 123 } 124 125 } 126 temp_num++; //步数 127 } 128 return 0; 129 } 130 131 132 int dis() //每个点之间的距离,另:需计算起点到终点的距离 133 { 134 for(int i=0;i<num;i++) 135 { 136 memset(vis,0,sizeof(vis)); //清内存 137 queue.clear(); //清队列 138 vis[fruits[i].x][fruits[i].y]=1; //置为浏览过 139 queue.push_back( map[fruits[i].x][fruits[i].y]); 140 141 int temp_num=0; //记录走了几步 142 int temp_n=0; //已发现的水果数量 143 while(queue.empty()==false) 144 { 145 int size=queue.size(); 146 for(int j=0;j<size;j++) 147 { 148 if(queue.front().energy>0) //此点有水果,保存距离 149 { 150 dist[i][queue.front().fru_num]=temp_num; 151 if(num==++temp_n)//各水果均已搜过。每搜到一水果就进行判断 152 { 153 queue.clear(); 154 break; 155 } 156 } 157 node temp=queue.front(); 158 queue.pop_front(); //出队 159 //将身边结点入队列,考虑四个方向 160 if(temp.x-1>=0 && map[temp.x-1][temp.y].energy>=0 && vis[temp.x-1][temp.y]==0) //同一行的,且未被访问过 161 { 162 vis[temp.x-1][temp.y]=1; //置为浏览过 163 queue.push_back( map[temp.x-1][temp.y] ); //入队列 164 } 165 if(temp.x+1<m && map[temp.x+1][temp.y].energy>=0 && vis[temp.x+1][temp.y]==0) //同一行的 166 { 167 vis[temp.x+1][temp.y]=1; 168 queue.push_back( map[temp.x+1][temp.y] ); 169 } 170 if(temp.y-1>=0 && map[temp.x][temp.y-1].energy>=0 && vis[temp.x][temp.y-1]==0) //同一列的 171 { 172 vis[temp.x][temp.y-1]=1; 173 queue.push_back( map[temp.x][temp.y-1] ); 174 } 175 if(temp.y+1<n && map[temp.x][temp.y+1].energy>=0 && vis[temp.x][temp.y+1]==0) //同一列的 176 { 177 vis[temp.x][temp.y+1]=1; 178 queue.push_back( map[temp.x][temp.y+1] ); 179 } 180 } 181 temp_num++; //步数 182 } 183 } 184 return 0; 185 } 186 187 188 //深搜求解。最大时17!次要计算。只挑1个,2个,3个。。。直到num个,就有num种。每一种都是乱序的。不知道如何实现。 189 int forth() 190 { 191 int ans=-1;//答案 192 stack<fruit> sta; 193 sta.push(fruits[0]); //[0][0],入口处的水果先进来 194 while(sta.empty()==false) //栈非空 195 { 196 197 } 198 } 199 200 int main() 201 { 202 int i,j; 203 while(cin>>m>>n) 204 { 205 num=0; 206 memset(fruits,0,sizeof(fruits)); 207 memset(map,0,sizeof(map)); 208 for(i=0;i<m;i++) 209 for(j=0;j<n;j++) 210 { 211 scanf("%d",&map[i][j].energy); 212 map[i][j].x=i; 213 map[i][j].y=j; 214 if(map[i][j].energy>0) 215 { 216 map[i][j].fru_num=num; //水果编号0~16 217 fruits[num].x=i; 218 fruits[num].y=j; 219 fruits[num++].energy=map[i][j].energy; 220 } 221 } 222 to_begin(); 223 to_end(); 224 dis(); 225 226 } 227 228 return 0; 229 }
时间: 2024-10-11 14:15:36