Untitled
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #ifdef _WIN32 #include <windows.h> // for Sleep() #define SLEEP(ms) Sleep(ms) #else #include <unistd.h> // for usleep() #define SLEEP(ms) usleep((ms)*1000) #endif // ----------------------------------------------------------------------------- // CONFIG // ----------------------------------------------------------------------------- #define NMAX 50 int N = 15; // Map dimension read from file // ----------------------------------------------------------------------------- // GLOBALS // ----------------------------------------------------------------------------- char mapData[NMAX][NMAX]; // The map: '0'=obstacle, '1'=soil, '2'=start, '3'=mission int visitedSoil[NMAX][NMAX]; int startR, startC; // The vehicle's anchor (top-left corner in its orientation) int totalFuel = 0; // Accumulates fuel usage // Orientation: 0=up, 1=right, 2=down, 3=left int dr[4] = {-1, 0, 1, 0}; int dc[4] = { 0, 1, 0, -1}; // ----------------------------------------------------------------------------- // VEHICLE SHAPE (2×3 or 3×2) // ----------------------------------------------------------------------------- #define NUM_VEHICLE_CELLS 6 // shapeOffsets[orientation][which_of_6_cells][0/1] int shapeOffsets[4][NUM_VEHICLE_CELLS][2] = { // orientation=0 (up) { {0,0},{0,1},{0,2}, {1,0},{1,1},{1,2} }, // orientation=1 (right) { {0,0},{1,0},{2,0}, {0,1},{1,1},{2,1} }, // orientation=2 (down) { {0,0},{0,1},{0,2}, {1,0},{1,1},{1,2} }, // orientation=3 (left) { {0,0},{1,0},{2,0}, {0,1},{1,1},{2,1} } }; // Check if all 6 cells for the 2×3 shape are valid (not '0', in-bounds) int validVehiclePosition(int r, int c, int dir) { int k; for(k=0; k<NUM_VEHICLE_CELLS; k++){ int rr = r + shapeOffsets[dir][k][0]; int cc = c + shapeOffsets[dir][k][1]; if(rr < 0 || rr >= N || cc < 0 || cc >= N) { return 0; } if(mapData[rr][cc] == '0') { return 0; } } return 1; } // ----------------------------------------------------------------------------- // STRUCTS // ----------------------------------------------------------------------------- typedef struct { int r, c; int dir; int cost; } State; typedef struct { int pr, pc, pdir; char moveType; } ParentInfo; typedef struct { State arr[NMAX*NMAX*4]; int size; } MinHeap; // ----------------------------------------------------------------------------- // MIN-HEAP (priority queue) UTILS // ----------------------------------------------------------------------------- int cmpState(State a, State b){ if(a.cost < b.cost) return -1; if(a.cost > b.cost) return 1; return 0; } void swap(State *a, State *b){ State tmp = *a; *a = *b; *b = tmp; } void pushHeap(MinHeap *h, State s){ h->arr[++h->size] = s; int idx = h->size; while(idx > 1 && cmpState(h->arr[idx], h->arr[idx/2]) < 0){ swap(&h->arr[idx], &h->arr[idx/2]); idx /= 2; } } State popHeap(MinHeap *h){ State ret = h->arr[1]; h->arr[1] = h->arr[h->size--]; int idx = 1; while(1){ int left = 2*idx, right = 2*idx+1; int smallest = idx; if(left <= h->size && cmpState(h->arr[left], h->arr[smallest]) < 0) { smallest = left; } if(right <= h->size && cmpState(h->arr[right], h->arr[smallest]) < 0){ smallest = right; } if(smallest == idx) break; swap(&h->arr[idx], &h->arr[smallest]); idx = smallest; } return ret; } int heapEmpty(MinHeap *h){ return (h->size == 0); } // ----------------------------------------------------------------------------- // PRINT MAP + VEHICLE // ----------------------------------------------------------------------------- void printMap(int rVehicle, int cVehicle, int dirVehicle){ #ifdef _WIN32 system("cls"); #else system("clear"); #endif static char display[NMAX][NMAX]; memcpy(display, mapData, sizeof(mapData)); int k; for(k=0; k<NUM_VEHICLE_CELLS; k++){ int rr = rVehicle + shapeOffsets[dirVehicle][k][0]; int cc = cVehicle + shapeOffsets[dirVehicle][k][1]; display[rr][cc] = 'R'; } int i,j; for(i=0; i<N; i++){ for(j=0; j<N; j++){ printf("%c ", display[i][j]); } printf("\n"); } printf("\nTotal fuel used: %d\n", totalFuel); } // ----------------------------------------------------------------------------- // SHIFT HELPER // ----------------------------------------------------------------------------- void shiftRC(int r, int c, int dir, int leftOrRight, int *rOut, int *cOut) { // leftOrRight: -1 => shift left, +1 => shift right switch(dir){ case 0: // up *rOut = r; *cOut = c + (leftOrRight * -1); break; case 1: // right *rOut = r + (leftOrRight * -1); *cOut = c; break; case 2: // down *rOut = r; *cOut = c + leftOrRight; break; case 3: // left *rOut = r + leftOrRight; *cOut = c; break; } } // ----------------------------------------------------------------------------- // UNIFORM-COST SEARCH (FOR MISSIONS) // ----------------------------------------------------------------------------- int distCost[NMAX][NMAX][4]; ParentInfo parentInfo[NMAX][NMAX][4]; int findPath(int sr, int sc, int sdir, int tr, int tc){ int r,c,d; for(r=0; r<N; r++){ for(c=0; c<N; c++){ for(d=0; d<4; d++){ distCost[r][c][d] = INT_MAX; parentInfo[r][c][d].pr = -1; parentInfo[r][c][d].pc = -1; parentInfo[r][c][d].pdir = -1; parentInfo[r][c][d].moveType = '?'; } } } distCost[sr][sc][sdir] = 0; MinHeap pq; pq.size = 0; pushHeap(&pq, (State){sr, sc, sdir, 0}); while(!heapEmpty(&pq)){ State st = popHeap(&pq); r = st.r; c = st.c; d = st.dir; int costSoFar = st.cost; // Skip stale if(costSoFar > distCost[r][c][d]) continue; // Goal check if(r == tr && c == tc){ return costSoFar; } // Expand neighbors: // 1) Forward { int rr = r + dr[d]; int cc = c + dc[d]; if(validVehiclePosition(rr, cc, d)){ int ncost = costSoFar + 1; if(ncost < distCost[rr][cc][d]){ distCost[rr][cc][d] = ncost; parentInfo[rr][cc][d] = (ParentInfo){r, c, d, 'F'}; pushHeap(&pq, (State){rr, cc, d, ncost}); } } } // 2) Backward { int rr = r - dr[d]; int cc = c - dc[d]; if(validVehiclePosition(rr, cc, d)){ int ncost = costSoFar + 1; if(ncost < distCost[rr][cc][d]){ distCost[rr][cc][d] = ncost; parentInfo[rr][cc][d] = (ParentInfo){r, c, d, 'B'}; pushHeap(&pq, (State){rr, cc, d, ncost}); } } } // 3) Turn left { int nd = (d + 3) % 4; int ncost = costSoFar + 3; if(validVehiclePosition(r, c, nd)){ if(ncost < distCost[r][c][nd]){ distCost[r][c][nd] = ncost; parentInfo[r][c][nd] = (ParentInfo){r, c, d, 'L'}; pushHeap(&pq, (State){r, c, nd, ncost}); } } } // 4) Turn right { int nd = (d + 1) % 4; int ncost = costSoFar + 3; if(validVehiclePosition(r, c, nd)){ if(ncost < distCost[r][c][nd]){ distCost[r][c][nd] = ncost; parentInfo[r][c][nd] = (ParentInfo){r, c, d, 'R'}; pushHeap(&pq, (State){r, c, nd, ncost}); } } } // 5) Shift left { int rr, cc; shiftRC(r, c, d, -1, &rr, &cc); int ncost = costSoFar + 3; if(validVehiclePosition(rr, cc, d)){ if(ncost < distCost[rr][cc][d]){ distCost[rr][cc][d] = ncost; parentInfo[rr][cc][d] = (ParentInfo){r, c, d, 'S'}; pushHeap(&pq, (State){rr, cc, d, ncost}); } } } // 6) Shift right { int rr, cc; shiftRC(r, c, d, +1, &rr, &cc); int ncost = costSoFar + 3; if(validVehiclePosition(rr, cc, d)){ if(ncost < distCost[rr][cc][d]){ distCost[rr][cc][d] = ncost; parentInfo[rr][cc][d] = (ParentInfo){r, c, d, 's'}; pushHeap(&pq, (State){rr, cc, d, ncost}); } } } } return -1; // unreachable } // ----------------------------------------------------------------------------- // RECONSTRUCT PATH + ANIMATE // ----------------------------------------------------------------------------- void reconstructAndMove(int targetR, int targetC){ // Find best orientation int bestDir = -1, bestCost = INT_MAX; int d; for(d=0; d<4; d++){ if(distCost[targetR][targetC][d] < bestCost){ bestCost = distCost[targetR][targetC][d]; bestDir = d; } } if(bestCost == INT_MAX){ return; // unreachable } static int PR[10000], PC[10000], PD[10000]; int pathLen = 0; int cr = targetR, cc = targetC, cd = bestDir; while(cd != -1){ PR[pathLen] = cr; PC[pathLen] = cc; PD[pathLen] = cd; ParentInfo p = parentInfo[cr][cc][cd]; int nr = p.pr, nc = p.pc, nd = p.pdir; cd = nd; cr = nr; cc = nc; if(cd < 0) break; pathLen++; } int i; for(i = pathLen - 1; i >= 0; i--){ int rr = PR[i]; int cc = PC[i]; int dd = PD[i]; // Increase totalFuel by cost difference if(i < pathLen - 1){ int rPrev = PR[i+1]; int cPrev = PC[i+1]; int dPrev = PD[i+1]; int costDiff = distCost[rr][cc][dd] - distCost[rPrev][cPrev][dPrev]; if(costDiff > 0) totalFuel += costDiff; } // Mark path if desired int k; for(k=0; k<NUM_VEHICLE_CELLS; k++){ int rCell = rr + shapeOffsets[dd][k][0]; int cCell = cc + shapeOffsets[dd][k][1]; if(mapData[rCell][cCell] == '1') mapData[rCell][cCell] = '*'; if(mapData[rCell][cCell] == '3') mapData[rCell][cCell] = '*'; } // Animate printMap(rr, cc, dd); SLEEP(200); } } // ----------------------------------------------------------------------------- // SHAPE-AWARE COVERAGE BFS // ----------------------------------------------------------------------------- void coverageBFS(int startR, int startC, int startDir) { // For coverage BFS, we store visited states in usedCover[r][c][d]. static int usedCover[NMAX][NMAX][4]; memset(usedCover, 0, sizeof(usedCover)); typedef struct { int r, c, d; } QState; QState queue[NMAX*NMAX*4]; int front = 0, back = 0; queue[back++] = (QState){ startR, startC, startDir }; usedCover[startR][startC][startDir] = 1; while(front < back){ QState u = queue[front++]; int r = u.r, c = u.c, d = u.d; // Mark the 6 occupied cells int k; for(k=0; k<NUM_VEHICLE_CELLS; k++){ int rr = r + shapeOffsets[d][k][0]; int cc = c + shapeOffsets[d][k][1]; if(mapData[rr][cc] == '1') mapData[rr][cc] = '*'; if(mapData[rr][cc] == '3') mapData[rr][cc] = '*'; } // Show the current vehicle position printMap(r, c, d); SLEEP(100); // We'll do the same 6 moves with costs. // Only add cost once if we haven't visited the neighbor state. // 1) Forward { int rr = r + dr[d]; int cc = c + dc[d]; if(validVehiclePosition(rr, cc, d) && !usedCover[rr][cc][d]){ usedCover[rr][cc][d] = 1; totalFuel += 1; // forward cost queue[back++] = (QState){ rr, cc, d }; printMap(rr, cc, d); SLEEP(100); } } // 2) Backward { int rr = r - dr[d]; int cc = c - dc[d]; if(validVehiclePosition(rr, cc, d) && !usedCover[rr][cc][d]){ usedCover[rr][cc][d] = 1; totalFuel += 1; // backward cost queue[back++] = (QState){ rr, cc, d }; printMap(rr, cc, d); SLEEP(100); } } // 3) Turn left { int nd = (d + 3) % 4; if(validVehiclePosition(r, c, nd) && !usedCover[r][c][nd]){ usedCover[r][c][nd] = 1; totalFuel += 3; queue[back++] = (QState){ r, c, nd }; printMap(r, c, nd); SLEEP(100); } } // 4) Turn right { int nd = (d + 1) % 4; if(validVehiclePosition(r, c, nd) && !usedCover[r][c][nd]){ usedCover[r][c][nd] = 1; totalFuel += 3; queue[back++] = (QState){ r, c, nd }; printMap(r, c, nd); SLEEP(100); } } // 5) Shift left { int rr, cc; shiftRC(r, c, d, -1, &rr, &cc); if(validVehiclePosition(rr, cc, d) && !usedCover[rr][cc][d]){ usedCover[rr][cc][d] = 1; totalFuel += 3; queue[back++] = (QState){ rr, cc, d }; printMap(rr, cc, d); SLEEP(100); } } // 6) Shift right { int rr, cc; shiftRC(r, c, d, +1, &rr, &cc); if(validVehiclePosition(rr, cc, d) && !usedCover[rr][cc][d]){ usedCover[rr][cc][d] = 1; totalFuel += 3; queue[back++] = (QState){ rr, cc, d }; printMap(rr, cc, d); SLEEP(100); } } } } // ----------------------------------------------------------------------------- // MAIN // ----------------------------------------------------------------------------- int main(){ // 1) Read map const char *filename = "input.txt"; FILE *fp = fopen(filename, "r"); if(!fp){ printf("Cannot open %s\n", filename); return 1; } N = 15; // or read from file int i; int foundStart = 0; for(i=0; i<N; i++){ fscanf(fp, "%s", mapData[i]); if((int)strlen(mapData[i]) < N){ printf("Map line %d is too short!\n", i); fclose(fp); return 1; } } fclose(fp); // 2) Find start cell '2' int j; for(i=0; i<N && !foundStart; i++){ for(j=0; j<N && !foundStart; j++){ if(mapData[i][j] == '2'){ startR = i; startC = j; foundStart = 1; } } } if(!foundStart){ printf("No start cell ('2') found!\n"); return 1; } // 3) Gather missions typedef struct {int r,c;} Node; Node missions[100]; int missionCount = 0; for(i=0; i<N; i++){ for(j=0; j<N; j++){ visitedSoil[i][j] = 0; if(mapData[i][j] == '3'){ missions[missionCount].r = i; missions[missionCount].c = j; missionCount++; } } } // initial orientation = 0 (up) int currR = startR; int currC = startC; int currDir = 0; totalFuel = 0; // 4) Visit each mission for(i=0; i<missionCount; i++){ int tr = missions[i].r; int tc = missions[i].c; int cost = findPath(currR, currC, currDir, tr, tc); if(cost < 0){ printf("Mission spot (%d, %d) unreachable!\n", tr, tc); continue; } reconstructAndMove(tr, tc); // figure out final orientation used int d, bestDir=-1, bestCost=INT_MAX; for(d=0; d<4; d++){ if(distCost[tr][tc][d] < bestCost){ bestCost = distCost[tr][tc][d]; bestDir = d; } } currR = tr; currC = tc; currDir = bestDir; } // 5) Coverage BFS from final (r,c,dir) coverageBFS(currR, currC, currDir); // Done printf("All missions processed. Coverage BFS done.\n"); printf("Final total fuel used: %d\n", totalFuel); return 0; }
Leave a Comment