// 寻找迷宫路径函数,如果存在出路,则把出路打印出来 void search_maze(int **maze, int **mark, TCellPtr pstack, int nrow, int ncol) { int move[4][2] ={{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; int top = 1; // 路径堆栈的栈顶指针 int found = 0; // 标记是否找到迷宫出路,found=1表示找到出路 int orientation = 0; // orientation存放当前元素正遍历的方位,0为右, 1为下, 2为左, 3为上 int next_row, next_col; // next_row, next_col分别存放当前元素的下一个元素的行列值 TCell curcell; // 当前迷宫单元 // 将迷宫入口单元压入栈顶(注意迷宫外围增设了一层“外墙”,所以入口坐标为(1,1)) pstack[0].row = 1; pstack[0].col = 1; pstack[0].dir = 0; mark[1][1] = 1; // 对迷宫入口元素进行标记,表明该单元已经走过 while(top >= 0 && !found){ // 如果栈非空(没有退回到入口单元),并且没有找到迷宫出口,则持续寻找路径 curcell = pstack[top--]; // 将栈顶元素出栈 orientation = curcell.dir; // 取栈顶元素的方向值为当前方向 // 以curcell的当前方向为起点,顺时针遍历邻居单元 while(orientation < 4 && !found){ //当4个方向没有遍历完,并且没有找到迷宫出口 next_row = curcell.row + move[orientation][0]; // 计算当前方向的邻居单元的行号 next_col = curcell.col + move[orientation][1]; // 计算当前方向的邻居单元的列号 if(next_row == nrow - 2 && next_col == ncol - 2){ found = 1; //如果邻居单元恰好为迷宫出口,将found标志置为1 } else if(!maze[next_row][next_col] && !mark[next_row][next_col]) { // 如果邻居单元可达,并且未被访问过 mark[next_row][next_col] = 1; // 将该单元标记为已访问 pstack[top].dir = ++orientation; // 当前元素的下一个方向赋值给当前元素 top++; //将此元素放入栈顶 pstack[top].row = next_row; pstack[top].col = next_col; pstack[top].dir = 0; curcell.row = next_row; curcell.col = next_col; orientation = 0; //方向控制dir清零 printf("%d %d\n", next_row, next_col); } else orientation++; }// while(dir < 4 && !found) }//while(top > -1 && !found) //如果找到迷宫出路,则调用地图输出函数;否则给出提示告诉用户该迷宫没有出路 if(found){ show_route(maze, pstack, nrow, ncol, top); } else{ printf("\n 该迷宫没有出路!\n"); } }
bool VRP::verify_routes(const char *message) { /// /// This debugging function will manually calculate the objective function of the current /// solution and the route values, etc., and compare with the claimed /// value. Returns false if any inconsistencies are found and prints /// the message. Returns true with no output otherwise. /// int i, n, cnt; double len=0; double rlen=0; double tot_len=0; int next_node; int current_node, current_route, route_start, flag, current_start, current_end; int total_load = 0; int current_load = 0; int num_in_route=0; int counted_routes=0; // First check the pred/next arrays for consistency current_node=VRPH_DEPOT; next_node=VRPH_ABS(this->next_array[current_node]); while(next_node!=VRPH_DEPOT) { if(VRPH_ABS(this->pred_array[next_node])!=current_node) { fprintf(stderr,"%d->%d??\nNext: %d->%d\nPred:%d->%d",current_node,next_node, current_node,this->next_array[current_node],next_node,this->pred_array[next_node]); report_error("%s: Next/pred inconsistency\n",__FUNCTION__); } current_node=next_node; next_node=VRPH_ABS(this->next_array[current_node]); } if(VRPH_ABS(this->pred_array[next_node])!=current_node) { fprintf(stderr,"%d->%d??\nNext: %d->%d\nPred:%d->%d",current_node,next_node, current_node,this->next_array[current_node],next_node,this->pred_array[next_node]); report_error("%s: Next/pred inconsistency\n",__FUNCTION__); } n=num_nodes; // Only consider the nodes in the solution! flag=0; i = 1; cnt = 0; route_start = -next_array[VRPH_DEPOT]; if(route_start < 0) { fprintf(stderr,"next[VRPH_DEPOT] is incorrect\n"); report_error(message,__FUNCTION__); } current_node = route_start; current_route = route_num[current_node]; current_start = route[current_route].start; current_end = route[current_route].end; counted_routes++; if(route_start != current_start) { fprintf(stderr,"Error in initial route start: %d != %d\n",route_start, current_start); report_error(message,__FUNCTION__); } total_load+=nodes[current_node].demand; current_load+=nodes[current_node].demand; len+=d[VRPH_DEPOT][current_node]; rlen+=d[VRPH_DEPOT][current_node]; if(current_node!= dummy_index) num_in_route++; while(route_start != 0 && i<num_nodes+1) { // When we finally get a route beginning at 0, this is the last route // and there is no next route, so break out if(next_array[current_node]==current_node) { // We've entered a loop fprintf(stderr,"Self loop found in next array(%d)\n",current_node); report_error("%s: Self loop!\n",__FUNCTION__); } if(next_array[current_node]==VRPH_DEPOT) { // We're at the end of the Solution! len+=d[current_node][VRPH_DEPOT]; rlen+=d[current_node][VRPH_DEPOT]; current_route=route_num[current_node]; tot_len+=rlen; if(num_in_route != route[current_route].num_customers) { fprintf(stderr,"Customer count error!!\nCounted(%d)!=Claimed(%d) in final route %d\n",num_in_route, route[current_route].num_customers,current_route); show_route(current_route); report_error(message); } // Now check the # of routes if(counted_routes != total_number_of_routes) { // error in # of routes fprintf(stderr, "Incorrect # of routes recorded %d!=%d\n",counted_routes, total_number_of_routes); report_error(message); } if(VRPH_ABS(len-total_route_length)<.01 && flag==0 ) { // everything looks good return true; } else { if(VRPH_ABS(len-total_route_length)>=.01) { fprintf(stderr,"Objective function error: calculated(%f)!=claimed(%f)\n",len, total_route_length); report_error(message); } report_error(message); } } if(next_array[current_node]>0) { // Next node is somewhere in the middle of a route next_node = next_array[current_node]; // Make sure current_node and next_node have the same route # if(route_num[current_node]!=route_num[next_node]) { fprintf(stderr,"Route # error for %d and %d: %d!=%d\n",current_node, next_node, route_num[current_node],route_num[next_node]); report_error(message); } len+=d[current_node][next_node]; rlen+=d[current_node][next_node]; current_node=next_node; if(current_node!= dummy_index) num_in_route++; total_load+=nodes[current_node].demand; current_load+=nodes[current_node].demand; cnt++; } else { // We must have a non-positive "next" node indicating the beginning of a new route len+=d[current_node][VRPH_DEPOT]; rlen+=d[current_node][VRPH_DEPOT]; tot_len+=rlen; current_route=route_num[current_node]; current_end = route[current_route].end; if(num_in_route != route[current_route].num_customers) { fprintf(stderr,"%d (calculated) != %d (claimed) in route %d\n",num_in_route, route[current_route].num_customers,current_route); show_route(current_route); // Report this now.. report_error(message); } if(current_node != current_end) { fprintf(stderr,"Error in route ends: %d!=%d\n",current_node, current_end); report_error(message); } if(VRPH_ABS(rlen-route[current_route].length)>.1) { fprintf(stderr,"Route Lengths: Calculated(%f)!=Claimed(%f)\n",rlen,route[current_route].length); int ii=route[current_route].start; int jj; fprintf(stderr,"0->%d = %f[%f]\n",ii, d[VRPH_DEPOT][ii], nodes[ii].service_time); while(ii != 0) { jj=VRPH_MAX(VRPH_DEPOT,next_array[ii]); fprintf(stderr,"%d->%d = %f[%f]\n",ii,jj,d[ii][jj], nodes[jj].service_time); ii=jj; } report_error(message); } if(current_load != route[current_route].load) { fprintf(stderr,"Route Loads: %d!=%d\n",current_load, route[current_route].load); report_error(message); } i++; route_start = - (next_array[current_node]); current_route = route_num[route_start]; current_start = route[current_route].start; current_end = route[current_route].end; counted_routes++; if(route_start != current_start) { fprintf(stderr,"Route %d: %d != %d\n",current_route, route_start, current_start); report_error(message); } current_node = route_start; total_load+=nodes[current_node].demand; // reset current_load to 0 current_load=nodes[current_node].demand; //len+=nodes[current_node].depot_distance; len+=d[VRPH_DEPOT][current_node]; // reset rlen to 0 //rlen=nodes[current_node].depot_distance; rlen=d[VRPH_DEPOT][current_node]; if(current_node!= dummy_index) num_in_route=1; else num_in_route=0; cnt++; } } return true; }
void route_command(const char *arg, struct session *ses) { char a[BUFFER_SIZE], b[BUFFER_SIZE], way[BUFFER_SIZE], dist[BUFFER_SIZE], cond[BUFFER_SIZE]; int j, d; arg=get_arg(arg, a, 0, ses); arg=get_arg(arg, b, 0, ses); arg=get_arg_in_braces(arg, way, 0); arg=get_arg(arg, dist, 0, ses); arg=get_arg_in_braces(arg, cond, 1); if (!*a) { tintin_printf(ses, "#THESE ROUTES HAVE BEEN DEFINED:"); for (int i=0;i<MAX_LOCATIONS;i++) for (struct routenode *r=ses->routes[i];r;r=r->next) show_route(ses, i, r); return; } if (!*way) { bool first=true; if (!*b) strcpy(b, "*"); for (int i=0;i<MAX_LOCATIONS;i++) if (ses->locations[i]&&match(a, ses->locations[i])) for (struct routenode *r=ses->routes[i];r;r=r->next) if (ses->locations[i]&& match(b, ses->locations[r->dest])) { if (first) { tintin_printf(ses, "#THESE ROUTES HAVE BEEN DEFINED:"); first=false; } show_route(ses, i, r); } if (first) tintin_printf(ses, "#THAT ROUTE (%s) IS NOT DEFINED.", b); return; } int i; for (i=0;i<MAX_LOCATIONS;i++) if (ses->locations[i]&&!strcmp(ses->locations[i], a)) goto found_i; if (i==MAX_LOCATIONS) { for (i=0;i<MAX_LOCATIONS;i++) if (!ses->locations[i]) { ses->locations[i]=mystrdup(a); goto found_i; } tintin_eprintf(ses, "#TOO MANY LOCATIONS!"); return; } found_i: for (j=0;j<MAX_LOCATIONS;j++) if (ses->locations[j]&&!strcmp(ses->locations[j], b)) goto found_j; if (j==MAX_LOCATIONS) { for (j=0;j<MAX_LOCATIONS;j++) if (!ses->locations[j]) { ses->locations[j]=mystrdup(b); goto found_j; } tintin_eprintf(ses, "#TOO MANY LOCATIONS!"); kill_unused_locations(ses); return; } found_j: if (*dist) { char *err; d=strtol(dist, &err, 0); if (*err) { tintin_eprintf(ses, "#Hey! Route length has to be a number! Got {%s}.", arg); kill_unused_locations(ses); return; } if ((d<0)&&(ses->mesvar[MSG_ROUTE]||ses->mesvar[MSG_ERROR])) tintin_eprintf(ses, "#Error: distance cannot be negative!"); } else d=DEFAULT_ROUTE_DISTANCE; addroute(ses, i, j, way, d, cond); if (ses->mesvar[MSG_ROUTE]) { if (*cond) tintin_printf(ses, "#Ok. Way from {%s} to {%s} is now set to {%s} (distance=%i) condition:{%s}", ses->locations[i], ses->locations[j], way, d, cond); else tintin_printf(ses, "#Ok. Way from {%s} to {%s} is now set to {%s} (distance=%i)", ses->locations[i], ses->locations[j], way, d); } routnum++; }
static int route(int fd,char *s) { char *nextargs = NULL, *arg; struct vder_route *ro; struct vder_iface *selected = NULL; struct in_addr temp_address, temp_netmask, temp_gateway; int metric = 1; enum command_action_enum action = -1; arg = strtok_r(s, " ", &nextargs); if(!arg) { /* No arguments */ ro = Router.routing_table; while(ro) { show_route(fd, ro); ro = ro->next; } return 0; } if ((!arg) || (strlen(arg) != 3) || ((strncmp(arg, "add", 3) != 0) && (strncmp(arg, "del", 3) != 0))) { printoutc(fd, "Invalid action \"%s\".", arg); return EINVAL; } if (strncmp(arg, "del", 3) == 0) action = ACTION_DELETE; else action = ACTION_ADD; arg = strtok_r(NULL, " ", &nextargs); if (!arg) { not_understood(fd, ""); return EINVAL; } if (match_input("default", arg)) { if (action == ACTION_ADD) action = ACTION_ADD_DEFAULT; if (action == ACTION_DELETE) { if (vder_route_del(0, 0, 1)) return errno; else return 0; } arg = strtok_r(NULL, " ", &nextargs); } if (!inet_aton(arg, &temp_address) || !is_unicast(temp_address.s_addr)) { printoutc(fd, "Invalid address \"%s\"", arg); return EINVAL; } if (action == ACTION_ADD_DEFAULT) { if (vder_route_add(0, 0, temp_address.s_addr, 1, NULL)) return errno; else return 0; } arg = strtok_r(NULL, " ", &nextargs); if (!arg) { printoutc(fd, "Error: parameter 'netmask' required."); return EINVAL; } if (!inet_aton(arg, &temp_netmask) || !is_netmask(temp_netmask.s_addr)) { printoutc(fd, "Invalid netmask \"%s\"", arg); return EINVAL; } arg = strtok_r(NULL, " ", &nextargs); while(arg) { if (match_input("via", arg)) { arg = strtok_r(NULL, " ", &nextargs); selected = select_interface(arg); if (!selected) return EINVAL; } else if (match_input("gw", arg)) { arg = strtok_r(NULL, " ", &nextargs); if (!inet_aton(arg, &temp_gateway) || !is_unicast(temp_gateway.s_addr)) { printoutc(fd, "Invalid gateway \"%s\"", arg); return EINVAL; } } else if (match_input("metric", arg)) { arg = strtok_r(NULL, " ", &nextargs); metric = atoi(arg); if (metric < 1) { printoutc(fd, "Invalid metric \"%s\"", arg); return EINVAL; } } else { return EINVAL; } arg = strtok_r(NULL, " ", &nextargs); } if ((action == ACTION_DELETE) && (vder_route_del(temp_address.s_addr, temp_netmask.s_addr, metric))) { return errno; } else if ((action == ACTION_ADD) && (vder_route_add(temp_address.s_addr, temp_netmask.s_addr, temp_gateway.s_addr, metric, selected))) { return errno; } return 0; }