#54183: 001


a0958789490@gmail.com (哈哈哈)


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DEST 10         // 目標位置
#define MAX_PATH 100    // 單條路徑最大長度
#define MAX_SOLUTIONS 50 // 最多儲存幾組最佳解 (避免記憶體爆掉)

// 全域變數
int best_paths[MAX_SOLUTIONS][MAX_PATH]; // 二維陣列:存多條路徑
int solution_count = 0;                  // 目前找到幾條最佳路徑

// 函式宣告
void line_mover(int, int, int*, int*, int);
void show_path(int*, int);

int main() {
    int path[MAX_PATH];
    int Nlim = 2 * (DEST > 0 ? DEST : -DEST) + 5; // 稍微放寬上限以防DEST太小
    if (Nlim < 10) Nlim = 20; // 基本保護

    // 初始化 moveMax
    int moveMax = Nlim + 1; 
    int *pMax = &moveMax;
    
    printf("Finding all optimal paths to %d...\n", DEST);
    
    line_mover(0, 0, path, pMax, Nlim);

    // 輸出結果
    if (solution_count == 0) {
        printf("No path found.\n");
    } else {
        printf("Found %d optimal path(s) with %d steps:\n", solution_count, *pMax);
        printf("--------------------------------------\n");
        for (int i = 0; i < solution_count; i++) {
            printf("Path %d: ", i + 1);
            show_path(best_paths[i], *pMax);
        }
    }

    return 0;
}

void show_path(int* path, int Nmov) {
    for (int i = 0; i < Nmov; i++) {
        if (path[i] > 0) printf("+%d", path[i]);
        else printf("%d", path[i]);
            
        if (i < Nmov - 1) printf(" -> ");
    }
    printf("\n");
}

void line_mover(int pos, int Nmov, int* path, int* moveMax, int Nlim) {
    
    // 檢查是否到達目的地
    if (pos == DEST) {
        // 情況 A:找到「更短」的路徑
        if (Nmov < *moveMax) {
            *moveMax = Nmov;     // 更新最短步數
            solution_count = 0;  // 清空之前找到的"較長"路徑
            
            // 存入這條新的最短路徑
            memcpy(best_paths[solution_count], path, sizeof(int) * Nmov);
            solution_count = 1;
        }
        // 情況 B:找到「長度相同」的另一條路徑
        else if (Nmov == *moveMax) {
            if (solution_count < MAX_SOLUTIONS) {
                memcpy(best_paths[solution_count], path, sizeof(int) * Nmov);
                solution_count++;
            }
        }
        return; 
    }

    // 剪枝與遞迴
    // 注意:這裡必須是 Nmov < *moveMax,
    // 因為如果 Nmov 已經等於 *moveMax,再走一步(Nmov+1)絕對會比最佳解長,所以不走。
    if (Nmov + 1 < Nlim && Nmov < *moveMax) {
        Nmov += 1; 
        
        // 向左
        path[Nmov - 1] = -Nmov;
        line_mover(pos - Nmov, Nmov, path, moveMax, Nlim);
        
        // 向右
        path[Nmov - 1] = Nmov;
        line_mover(pos + Nmov, Nmov, path, moveMax, Nlim);
    }
}