Ø
要将一张
100
元的大钞票,换成等值的
10
元、
5
元、
2
元、
1
元一张的小
钞票,每次换成
40
张小钞票,每种至少
1
张。如,有一种换法:
Ø
10
元:
1
张
Ø
5
元:
5
张
Ø
2
元:
31
张
Ø
1
元:
3
张
Ø
问:一共有多少种换法。
数学模型:
View Code
View Code
View Code
View Code
Ø
10元: a 张 (不超过10张)
Ø
5元: b 张 (不超过20张)
Ø
2元: c 张 (不超过50张)
Ø
1元: d 张 (不超过100张)
Ø
不定方程:
Ø
10*a+5*b+2*c+d=100
Ø
a+b+c+d=40
Ø
a>=1;b>=1;c>=1;d>=1
Ø
方程有多少组正整数解?
方法1:
枚举abcd


#include<cstdio> int main(){ int s=0,a,b,c,d; for(a=1;a<=10;a++) for(b=1;b<=20;b++) for(c=1;c<=50;c++) for(d=1;d<=100;d++) if(a+b+c+d==40 && 10*a+5*b+2*c+d==100){ s=s+1; printf("%d : %d %d %d %d\n",s,a,b,c,d); } return 0; }
思考如何减少一层循环
方法2:


#include<cstdio> int main(){ int s=0,a,b,c,d; for(a=1;a<=10;a++) for(b=1;b<=20;b++) for(c=1;c<=40;c++){ d=40-(a+b+c); if(d>0&&10*a+5*b+2*c+d==100){ s=s+1; printf("%d : %d %d %d %d\n",s,a,b,c,d); } } return 0; }
还能再减少一层循环吗?
方法3:
Ø
根据不定方程:
Ø
10*a+5*b+2*c+d=100
Ø
a+b+c+d=40
Ø
可得:
c=60-(9*a+4*b);
d=8*a+3*b-20;
这也只枚举a b即可。


#include<cstdio> int main(){ int s=0,a,b,c,d; for(a=1;a<=10;a++) for(b=1;b<=20;b++){ c=60-(9*a+4*b); d=8*a+3*b-20; if(c>0&&d>0){ s=s+1; printf("%d : %d %d %d %d\n",s,a,b,c,d); } } return 0; }
还可以继续优化吗?
方法4:
从枚举的范围进行优化


#include<cstdio> int main(){ int s=0,a,b,c,d; for(a=1;a<=7;a++) for(b=1;b<=17;b++){ c=60-(9*a+4*b); d=8*a+3*b-20; if(c>0&&d>0){ s=s+1; printf("%d : %d %d %d %d\n",s,a,b,c,d); } } return 0; }
结论:
即使采用暴力枚举,也要认真分析问题。
常用的枚举优化措施
:
(
1
)减少枚举层数;
(
2
)减少每一层的循环次数