Money Changing Problem 的各種延伸問題
能否湊得某個價位( Money Changing Problem )
湊得某個價位的湊法共有幾種( Coin Change Problem )
湊得某個價位的最少錢幣用量( Change-Making Problem )
湊得某個價位的錢幣用量,有哪幾種可能性。
能否湊得某個價位,但是錢幣限量供應。
能否湊得某個價位( Money Changing Problem )
- int price[5] = {5, 2, 6, 11, 17}; // 各種面額,順序可隨意。
- bool c[1000+1];
- // 看看 {5, 2, 6, 11, 17} 這些面額湊不湊得到價位 m
- void change(int m)
- {
- memset(c, false, sizeof(c));
- c[0] = true;
- for (int i = 0; i < 5; ++i) // 依序加入各種面額
- for (int j = price[i]; j <= m; ++j) // 由低價位逐步到高價位
- c[j] ||= c[j-price[i]]; // 湊、湊、湊
- if (c[m])
- cout << "湊得到";
- else
- cout << "湊不到";
- }
- int price[5] = {5, 2, 6, 11, 17};
- int c[5][1000+1]; // 大於等於0代表該問題有計算過,-1代表沒計算過。
- // 一開始必須全部初始化為-1。
- void change(int n, int m)
- {
- if (n < 0 || m < 0) return 0; // 0 代表 false
- if (m == 0) return 1; // 1 代表 true
- if (c[n][m] != -1) return c[n][m];
- return c[n][m] = change(n-1, m) | change(n, m - price[n]);
- }
湊得某個價位的湊法共有幾種( Coin Change Problem )
- int price[5] = {5, 2, 6, 11, 17};
- int c[1000+1];
- void change(int m)
- {
- memset(c, 0, sizeof(c));
- c[0] = 1;
- for (int i = 0; i < 5; ++i)
- for (int j = price[i]; j <= m; ++j)
- c[j] += c[j-price[i]];
- cout << "湊得價位" << m << "的湊法有" << c[m] << "種";
- }
湊得某個價位的最少錢幣用量( Change-Making Problem )
- int price[5] = {5, 2, 6, 11, 17};
- int c[1000+1];
- void change(int m)
- {
- memset(c, 0x7f, sizeof(c));
- c[0] = 0;
- for (int i = 0; i < 5; ++i)
- for (int j = price[i]; j <= m; ++j)
- c[j] = min(c[j], c[j-price[i]] + 1);
- cout << "湊得價位" << m;
- cout << "最少需(只)要" << c[m] << "個錢幣";
- }
湊得某個價位的錢幣用量,有哪幾種可能性。
- int price[5] = {5, 2, 6, 11, 17};
- long long c[1000]; // 每一格都是一個bitset,
- // 紀錄該價位可用幾個錢幣湊得,包含各種可能性。
- void change(int m)
- {
- memset(c, 0, sizeof(c));
- c[0] = 1;
- for (int i = 0; i < 5; ++i)
- for (int j = price[i]; j <= m; ++j)
- // 錢幣數量加一,每一種可能性都加一。
- c[j] |= c[j-price[i]] << 1;
- for (int i = 1; i <= 63; ++i)
- if (c[m] & (1 << i))
- cout << "用" << i << "個錢幣可湊得價位" << m;
- }
能否湊得某個價位,但是錢幣限量供應。
- int price[5] = {5, 2, 6, 11, 17};
- int num[5] = {4, 5, 5, 3, 2}; // 各種面額的供應量
- bool c[1000+1];
- void change(int m)
- {
- memset(c, 0, sizeof(c));
- c[0] = true;
- for (int i = 0; i < 5; ++i)
- for (int k = 0; k < M[i]; ++k) // 各種餘數分開處理
- // for (int k = 1; k <= M[i]; ++k) // 快了那麼一點的寫法
- {
- int left = T[i];
- for (int j = k; j <= m; j += M[i]) // 由低價位到高價位
- // 用第0種到第i種面額已能湊得,錢幣可以省著用。
- if (c[j])
- {
- left = T[i]; // 補充彈藥
- }
- // 過去都無法湊得,一定要試著用目前面額硬湊。
- else if (left > 0)
- {
- left--; // 用掉一個錢幣
- c[j] = true;
- }
- }
- if (c[m])
- cout << "湊得到";
- else
- cout << "湊不到";
- }
留言
張貼留言