程式設計也快樂第三期解答(二)
多個水壺的情況
在昨天的文章中,我們的演算法只處理前兩個水壺。現在讓我們修改演算法,處理輸入的所有水壺。下面就是修改後的Water.cs
:
1: using System;
2: using System.IO;
3: using Skyiv.Extensions;
4:
5: namespace Skyiv.Ben.Pond
6: {
7: sealed class Water
8: {
9: TextWriter writer; // 往哪寫?
10: int limit; // 解決方案的步數限制
11: int target; // 要達到的目標
12: Kettle[] kettles; // 水壺們: 最少兩個
13:
14: public Water(TextWriter writer, int limit, int target, params int[] capacitys)
15: { // 建構函式
16: this.writer = writer;
17: this.limit = limit;
18: this.target = target;
19: kettles = new Kettle[capacitys.Length];
20: for (var i = 0; i < capacitys.Length; i++)
21: kettles[i] = new Kettle(((char)('A' + i)).ToString(), capacitys[i]);
22: }
23:
24: public void Solve()
25: { // 尋找解決步驟
26: writer.Write("步數限制:{0} 目標:{1} 水壺們:", limit, target);
27: foreach (var kettle in kettles) writer.Write(kettle);
28: writer.WriteLine(); // 以上三行輸出題目的條件
29: for (int i = 0, k = 1; ; k = -k)
30: { // 主迴圈,演算法2
31: if (k > 0) Solve(++i, kettles[kettles.Length - 1].FullUp);
32: else Solve(++i, kettles[0].Clean);
33: for (var j = kettles.Length - 1; j > 0; j--)
34: Solve(++i, kettles[j].Move, kettles[j - 1]);
35: }
36: }
37:
38: void Solve(int step, Func<string> func)
39: { // 適用於無引數動作:倒空水壺、裝滿水壺
40: Solve(step, func());
41: }
42:
43: void Solve(int step, Func<Kettle, string> func, Kettle other)
44: { // 適用於一個引數的動作:將水倒入另一隻壺中
45: Solve(step, func(other));
46: }
47:
48: void Solve(int step, string func)
49: { // 解決步驟的一步
50: writer.Write("{0,3}: {1}", step, func.ChinesePadRight(14));
51: foreach (var kettle in kettles) writer.Write(kettle);
52: writer.WriteLine();
53: var isFinished = IsFinished();
54: if (step < limit && !isFinished) return;
55: if (isFinished) writer.WriteLine("---- 大功告成 ---------------");
56: else if (step >= limit) writer.WriteLine("**** 出師未捷身先死 ****");
57: Environment.Exit(0);
58: }
59:
60: bool IsFinished()
61: { // 是否完成任務?
62: foreach (var kettle in kettles)
63: if (kettle.Current == target) return true;
64: return false;
65: }
66: }
67: }
注意,對比昨天的演算法1
,我們今天的演算法2
只修改了Water.cs
原始檔中第 29~35 行的主迴圈,其餘程式碼都沒有變動。其餘的 C# 檔案也沒有改動。我們今天的演算法2
在主迴圈中反覆執行以下步驟:
- 裝滿最後一個水壺。
- 將水從最後一個水壺依次倒入前一個水壺,直至第一個水壺。
- 倒空第一個水壺。
- 將水從最後一個水壺依次倒入前一個水壺,直至第一個水壺。
直到完成任務,或者達到步數限制。可以看出,如果只有兩個水壺,這個演算法2
和演算法1
是一樣的。
編譯和執行
好了,讓我們來編譯和執行吧:
Water$ make && mono ConsoleRunner.exe 3 5 6
dmcs -out:ConsoleRunner.exe ConsoleRunner.cs Water.cs Kettle.cs StringExtensions.cs
步數限制:20 目標:3 水壺們:[A:0/5][B:0/6]
1: [裝滿:B] [A:0/5][B:6/6]
2: [從B倒入A:5] [A:5/5][B:1/6]
3: [倒空:A] [A:0/5][B:1/6]
4: [從B倒入A:1] [A:1/5][B:0/6]
5: [裝滿:B] [A:1/5][B:6/6]
6: [從B倒入A:4] [A:5/5][B:2/6]
7: [倒空:A] [A:0/5][B:2/6]
8: [從B倒入A:2] [A:2/5][B:0/6]
9: [裝滿:B] [A:2/5][B:6/6]
10: [從B倒入A:3] [A:5/5][B:3/6]
---- 大功告成 ---------------
這是兩個水壺的情況,不出所料,執行結果和昨天演算法1
的一樣。 注意在這裡我們用&&
連線make
和mono
命令,在同一個命令列編譯和執行,在除錯程式時很方便。如果編譯出錯的話,後面的執行命令是不會執行的。下面是更多的水壺的執行例項:
Water$ mono ConsoleRunner.exe 8 2 5 7 12
步數限制:20 目標:8 水壺們:[A:0/2][B:0/5][C:0/7][D:0/12]
1: [裝滿:D] [A:0/2][B:0/5][C:0/7][D:12/12]
2: [從D倒入C:7] [A:0/2][B:0/5][C:7/7][D:5/12]
3: [從C倒入B:5] [A:0/2][B:5/5][C:2/7][D:5/12]
4: [從B倒入A:2] [A:2/2][B:3/5][C:2/7][D:5/12]
5: [倒空:A] [A:0/2][B:3/5][C:2/7][D:5/12]
6: [從D倒入C:5] [A:0/2][B:3/5][C:7/7][D:0/12]
7: [從C倒入B:2] [A:0/2][B:5/5][C:5/7][D:0/12]
8: [從B倒入A:2] [A:2/2][B:3/5][C:5/7][D:0/12]
9: [裝滿:D] [A:2/2][B:3/5][C:5/7][D:12/12]
10: [從D倒入C:2] [A:2/2][B:3/5][C:7/7][D:10/12]
11: [從C倒入B:2] [A:2/2][B:5/5][C:5/7][D:10/12]
12: [從B倒入A:0] [A:2/2][B:5/5][C:5/7][D:10/12]
13: [倒空:A] [A:0/2][B:5/5][C:5/7][D:10/12]
14: [從D倒入C:2] [A:0/2][B:5/5][C:7/7][D:8/12]
---- 大功告成 ---------------
要注意的是,這個演算法2
同昨天的演算法1
一樣,也不是一定可以找到解答的。如果找到解答,也不一定是最優的。
相關文章
- 程式設計也快樂第三期解答(四)程式設計
- 程式設計也快樂第三期解答(三)程式設計
- 程式設計也快樂第三期解答(一)程式設計
- 程式設計也快樂第3期SQL程式碼程式設計SQL
- 程式設計也快樂: 兩隻水壺 C程式碼 搜尋版程式設計C程式
- 程式設計師節快樂程式設計師
- 使用Google Guava快樂程式設計GoGuava程式設計
- 程式設計師的快樂生活程式設計師
- 快樂指南:程式設計師版程式設計師
- 1024!程式設計師節快樂!程式設計師
- 女程式設計師們!節日快樂!程式設計師
- 程式設計師如何祝自己生日快樂程式設計師
- 程式設計學習之路:痛並快樂著程式設計
- 程式設計師的快樂:那些小細節程式設計師
- 讓程式設計快樂起來的過程程式設計
- 程式設計師快樂器之JAVA程式碼生成工具程式設計師Java
- 編碼也快樂:兩隻水壺F#程式
- 編碼也快樂:兩隻水壺Scheme程式Scheme
- 編碼也快樂:兩隻水壺C#程式C#
- 華為大佬:做一個快樂的程式設計師程式設計師
- 調查:是什麼讓程式設計師快樂?程式設計師
- 快樂Node程式設計師的10個習慣程式設計師
- 《Ruby基礎教程(第4版)》:快樂程式設計程式設計
- 在程式設計中體驗純粹的快樂程式設計
- 編碼也快樂:兩水壺的故事之JS程式JS
- 五線譜入門,程式設計師也可以玩音樂程式設計師
- 快樂的星期天:Scratch少兒趣味程式設計程式設計
- 程式設計師保持天天快樂的6個習慣程式設計師
- 程式設計師的燈下黑:沒學會快樂程式設計師
- 傳播正能量——做一個快樂的程式設計師程式設計師
- 《快樂碼農》第5期 大話程式設計師面試程式設計師面試
- 編碼也快樂活動:撲克牌排序排序
- 編碼也快樂!撲克牌排序JAVA排序Java
- Java程式設計師面試題及解答Java程式設計師面試題
- 也談程式設計改革程式設計
- 《Python程式設計練習與解答》之程式設計概論Python程式設計
- 聖誕節快樂:來自程式設計師們的問候程式設計師
- 程式設計師保持快樂活躍的6個好習慣程式設計師