貪心演算法

貪心演算法,每一次都盡可能「挑最大」。

零錢組合

只有以下二種硬幣,請問可以湊成11元,最少的硬幣組合方式。

5元 1元

貪心演算法,每一次挑最大。

第1次

選5元,挑最大硬幣。

11 - 5 = 6

第2次

選5元,挑最大硬幣。

6 - 5 = 1

第3次

不能選5元,因為餘額只剩下1元,只能挑1元。

1 - 1 = 0

所以總共使用2個5元硬幣,與1個1元硬幣。

零錢組合2

只有以下二種硬幣,請問可以湊成11元,最少的硬幣組合方式。

5元 3元

貪心演算法,每一次挑最大。

第1次

選5元,挑最大硬幣。

11 - 5 = 6

第2次

選5元,挑最大硬幣。

6 - 5 = 1

第3次

有餘額,而且不夠減,策略有問題,backtracking退回前一個步驟。

1 - 3 = 不夠減

回到第2次

選3元

6 - 3 = 3

第3次

選3元

3 - 3 = 0

總共使用1個5元硬幣,與2個3元硬幣。

基地台涵蓋問題

基地台涵蓋的所有地區:

台北, 台東, 彰化, 花蓮, 高雄, 澎湖, 苗栗, 宜蘭

各個基地台涵蓋的範圍如下:

基地台編號 涵蓋範圍
0 台北 台東 彰化
1 花蓮 高雄 澎湖
2 苗栗 宜蘭 台北
3 苗栗 高雄
4 澎湖 宜蘭

請問可以涵蓋所有地區的基地台組合有那些?
答案是:0號、1號、2號。

程式步驟

第1次

統計涵蓋數量。

基地台編號 涵蓋範圍 數量
0 台北 台東 彰化 3
1 花蓮 高雄 澎湖 3
2 苗栗 宜蘭 台北 3
3 苗栗 高雄 2
4 澎湖 宜蘭 2

找出上面涵蓋數量「最大」的基地台編號,基地台0號、1號、2號都是數量3,排序由編號最小的開始,此次涵蓋數量最大的基地台是0,把0號儲存在清單。

基地台編號 涵蓋範圍 數量
0 台北 台東 彰化 3

list清單

0

基地台0號的涵蓋範圍台北、台東、彰化。
以下所有涵蓋地區若在基地台0號的範圍內,則刪掉。

台北, 台東, 彰化, 花蓮, 高雄, 澎湖, 苗栗, 宜蘭

刪除完變這樣:

花蓮, 高雄, 澎湖, 苗栗, 宜蘭

第2次

基地台涵蓋地區

花蓮, 高雄, 澎湖, 苗栗, 宜蘭
基地台編號 涵蓋範圍 數量
0 台北 台東 彰化 0
1 花蓮 高雄 澎湖 3
2 苗栗 宜蘭 台北 2
3 苗栗 高雄 2
4 澎湖 宜蘭 2

找出上面涵蓋數量「最大」的基地台編號,此次涵蓋數量最大的基地台是1,把1號儲存在清單。

list清單

0, 1

基地台1號的涵蓋範圍花蓮 高雄 澎湖。
以下所有涵蓋地區若在基地台1號的範圍內,則刪掉。

花蓮, 高雄, 澎湖, 苗栗, 宜蘭

刪除完變這樣:

苗栗, 宜蘭

第3次

基地台涵蓋地區

苗栗, 宜蘭
基地台編號 涵蓋範圍 數量
0 台北 台東 彰化 0
1 花蓮 高雄 澎湖 0
2 苗栗 宜蘭 台北 2
3 苗栗 高雄 1
4 澎湖 宜蘭 1

找出上面涵蓋數量「最大」的基地台編號,此次涵蓋數量最大的基地台是2,把2號儲存在清單。

list清單

0, 1, 2

基地台2號的涵蓋範圍苗栗 宜蘭 台北。
以下所有涵蓋地區若在基地台2號的範圍內,則刪掉。

苗栗, 宜蘭

刪除完變這樣:


刪除變空,就可以結束。

程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class BaseStation {
  public static void main(String[] args) {
    String[] area = new String[]{"台北", "台東", "彰化", "花蓮", "高雄","澎湖","苗栗","宜蘭"};
    List areaList = new ArrayList(Arrays.asList(area));
    List<List<String>> baseStation = new ArrayList<>();
    baseStation.add(0, Arrays.asList("台北", "台東", "彰化"));
    baseStation.add(1, Arrays.asList("花蓮", "高雄", "澎湖"));
    baseStation.add(2, Arrays.asList("苗栗", "宜蘭", "台北"));
    baseStation.add(3, Arrays.asList("苗栗", "高雄"));
    baseStation.add(4, Arrays.asList("澎湖","宜蘭"));
    List<Integer> result = new ArrayList<>();
    // 刪到所有涵蓋範圍為0,才停止。
    while (areaList.size() > 0) {
      // 此次最大涵蓋的基地台編號
      int maxKey = -1;
      // 基地台涵蓋數量
      int maxCnt = 0;
      // 遍歷所有基地台
      for (int i = 0; i < baseStation.size(); i++) {
        // 基地台涵蓋地區清單
        List subList = baseStation.get(i);
        // 涵蓋地區數量
        int count = contains(areaList, subList);
        // 此基地台涵蓋數量是否為最大?
        if (count > maxCnt) {
          maxKey = i;
          maxCnt = count;
        }
      }
      // 所有地區包含在「最大涵蓋的基地台」地區範圍,則刪除
      containsRemove(areaList, baseStation.get(maxKey));
      // 儲存最大涵蓋的基地台
      result.add(maxKey);
    }
    System.out.println("result=" + result);
  }
  // 涵蓋地區數量計算
  public static int contains(List<String> areaList,List<String> subList) {
    int count = 0;
    for (int i = 0; i < areaList.size(); i++) {
      if (subList.contains(areaList.get(i))) {
        count++;
      }
    }
    return count;
  }
  // 所有地區包含在「最大涵蓋的基地台」地區範圍,則刪除
  public static void containsRemove(List<String> areaList,List<String> subList) {
    for (int i = 0; i < subList.size(); i++) {
      if (areaList.contains(subList.get(i))) {
        areaList.remove(subList.get(i));
      }
    }
  }
}
result=[0, 1, 2]

results matching ""

    No results matching ""