商店有面值为25分、10分、5分、1分的硬币,给出各硬币的数量和要找给顾客的钱数,问怎么使找给顾客的总的硬币数最少。
重温DFS,先是用了最暴力的方法,枚举所有的情况
#include<stdio.h>
int m[5], cnt, res[5], num[5], C, MIN;
int c[] = {25, 10, 5, 1};
void dfs(int d)
{
int i, sum, n;
if(d > 3)
{
for(i = sum = n = 0; i < 4; i ++)
{
sum += c[i]*num[i];
n += num[i];
}
if(sum == C)
{
if(n < MIN)
{
for(i = 0; i < 4; i ++)
res[i] = num[i];
MIN = n;
}
cnt++;
}
}
else
{
for(i = 0; i <= m[d]; i ++)
{
num[d] = i;
dfs(d+1);
}
}
}
int main(){
while(scanf("%d%d%d%d%d", &m[0], &m[1], &m[2], &m[3], &C), m[0]||m[1]||m[2]||m[3]||C)
{
MIN = m[0]+m[1]+m[2]+m[3]+1;
cnt = 0;
dfs(0);
if(cnt == 0) printf("Cannot dispense the desired amount.\n");
else printf("Dispense %d quarters, %d dimes, %d nickels, and %d pennies.\n", res[0], res[1], res[2], res[3]);
}
return 0;
}
然后优化了一下,已经超出钱数,或者已经满足钱数,就不继续搜索了
#include<stdio.h>
int m[5], cnt, res[5], num[5], C, MIN;
int c[] = {25, 10, 5, 1};
void dfs(int d, int tot)
{
int i, j, n, temp;
if(d > 3)
{
return;
}
else
{
for(i = 0; i <= m[d]; i ++)
{
temp = tot - i*c[d];
if(temp < 0) break;
else if(temp == 0)
{
cnt++;
for(j = n = 0; j < d; j ++) n += num[j];
if(n+i < MIN)
{
for(j = 0; j < d; j ++)
{
res[j] = num[j];
}
res[d] = i;
for(j = d+1; j < 4; j ++)
{
res[j] = 0;
}
MIN = n+i;
}
break;
}
else
{
num[d] = i;
dfs(d+1, temp);
}
}
}
}
int main(){
while(scanf("%d%d%d%d%d", &m[0], &m[1], &m[2], &m[3], &C), m[0]||m[1]||m[2]||m[3]||C)
{
MIN = m[0]+m[1]+m[2]+m[3]+1;
cnt = 0;
dfs(0, C);
if(cnt == 0) printf("Cannot dispense the desired amount.\n");
else printf("Dispense %d quarters, %d dimes, %d nickels, and %d pennies.\n", res[0], res[1], res[2], res[3]);
}
return 0;
}
在POJ提交都是0ms……看来这道题数据比较弱。