給定三個容量不同的水杯,初始時只有最大的水杯裝滿水,其餘兩杯為空。水杯無刻度標記,只能根據已知容量計算水量。任務是編寫程序,找出從初始狀態到達目標狀態所需的最少倒水次數。
輸入包含多組測試數據。每組給出三個水杯的體積 V1、V2、V3(滿足 V1 > V2 > V3,V1 < 100,V3 > 0),以及目標狀態 E1、E2、E3(各不超過對應水杯容量)。輸出最少倒水次數,若無法達到目標則輸出 -1。
將每個狀態視為圖中的一個節點,狀態由三杯當前水量 (x, y, z) 表示。從初始狀態出發,通過六種可能的倒水操作(任意兩杯之間互倒)生成新狀態,使用 BFS 尋找最短路徑。
vis[x][y][z] 記錄訪問狀態,f[x][y][z] 記錄前驅節點以重構路徑。struct Node { int x, y, z; };
queue<Node> q;
bool vis[101][101][101];
Node pre[101][101][101];
void tryPush(const Node& u, Node v) {
if (!vis[v.x][v.y][v.z]) {
vis[v.x][v.y][v.z] = true;
pre[v.x][v.y][v.z] = u;
q.push(v);
}
}
// 六種倒水操作
// 1: 0->1, 2: 0->2, 3: 1->0, 4: 1->2, 5: 2->0, 6: 2->1
// 循環調用 tryPush 直到找到目標或隊列為空
狀態空間上限為 100×100×100 = 106,BFS 時間與空間複雜度均為 O(V1·V2·V3),在題目限制下完全可行。
輸入:6 3 1 4 1 1 (容量 6,3,1;目標 4,1,1)
最短路徑:(6,0,0) → (3,3,0) → (4,2,0) → (4,1,1),共 3 步。