找零问题的各种延伸问题
能否凑得某个价位(找零问题)
-
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]);
-
}
凑得某个价位的凑法共有几种(硬币找零问题)
-
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] << "种";
-
}
凑得某个价位的最少钱币用量(找零问题)
-
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 << "凑不到";
-
}