1
目的:
1.理解穷举法
2.掌握排列的应用
实验内容:
1.简单枚举
在枚举复杂对象之前,先尝试着枚举一些相对简单的内容,如整数、子串等。尽管暴力枚举不用太动脑筋,但对问题进行一定的分析往往会让算法更加简洁、高效。
提示7-1:即使采用暴力法求解问题,对问题进行一定的分析往往会让算法更简洁、高效。
例题7-1 除法(Division, UVa 725)
输入正整数n,按从小到大的顺序输出所有形如abcde/fghij= n的表达式,其中a~j恰好为数字0~9的一个排列(可以有前导0),2≤n≤79。
样例输入:
62
样例输出:
79546 / 01283 = 62
94736 / 01528 = 62
【分析】
枚举0~9的所有排列?没这个必要。只需要枚举fghij就可以算出abcde,然后判断是否所有数字都不相同即可。不仅程序简单,而且枚举量也从10!=3628800降低至不到1万,而且当abcde和fghij加起来超过10位时可以终止枚举。由此可见,即使采用暴力枚举,也是需要认真分析问题的。
编程思路
假设变量 x / y = n
定义长度为10的数组 int a[10];来统计x,y中各个数字出现的频率。
当 a[10] = {1,1,1,1,1,1,1,1,1,1}时,表示所有数字都出现了,即x和y符合我们的要求。这时输出结果。
#include <stdio.h>
//判断数字的位数
int intlen(int nums){
int i=0;
while(nums > 0){
nums = nums /10;
i++;
}
return i;
}
//判断数组是否全为1
int all_one(int a[],int x,int y){
int i;
int xx = x;
if(intlen(x)>5){
return 0;
}
// 统计x中数字出现的频率
for(i=0;i<intlen(xx);i++){
// printf(" %d\n",x%10);
a[x%10] = a[x%10] + 1;
x = x / 10;
}
//统计y中数字出现的频率
int yy = y;
if (intlen(yy) <5){
a[0] = 1;
}
for(i=0;i<intlen(yy);i++){
// printf(" %d\n",y%10);
a[y%10] = a[y%10] + 1;
y = y / 10;
}
//判断是否全为1
for(i=0;i<10;i++){
if (a[i] != 1){
return 0;
}
}
return 1;
}
int main(){
int n = 15;
int i;
int a[10];
int y;
int x;
for(y=0;y<99999;y++){
x = y * n;
// 初始化数组
for(i=0;i<10;i++){
a[i] = 0;
}
//判断是否全为1
if (all_one(a,x,y) == 1){
printf("%d / %d = %d\n",x,y,n);
}
}
return 0;
}
n = 15的结果
2.猜数字
46*79=23*158
要求找出所有的乘法等式,并1-9个数字只能用一次。
编程思路
将一个九位数拆成4个数,如467923158 -》 46,79,23,158
然后将四个数字按上面的乘法相乘,判断是否符合要求,符合即输出。
这里要去掉两种情况,1.有零出现。2.数字重复出现。方法与上一题一样,统计各个数字出现的频率。
#include <stdio.h>
int intlen(int nums){
int i=0;
while(nums > 0){
nums = nums /10;
i++;
}
return i;
}
//判断是否符合要求
int all_one(int* a_nums){
int i;
if (intlen(a_nums[0]) < 2 || intlen(a_nums[1]) < 2 || intlen(a_nums[2]) < 2 || intlen(a_nums[3]) < 3){
return 0;
}
//初始化数组
int a[10];
for (i=0;i<10;i++){
a[i] = 0;
}
//统计数字出现的频率
for (i=0;i<4;i++){
int x = a_nums[i];
int xx = x;
int j;
for(j=0;j<intlen(xx);j++){
a[x%10] = a[x%10] + 1;
x = x / 10;
}
}
//如果0出现,就去掉
if (a[0] == 1){
return 0;
}
//判断是否全为1
for(i = 1;i<10;i++){
if(a[i] != 1){
return 0;
}
}
return 1;
}
//拆分数字
void get_nums(int num,int* a){
int num1 = (num / 100000)/100;
int num2 = (num / 100000)%100;
int num3 = (num % 100000)/1000;
int num4 = (num % 100000)%1000;
a[0] = num1;
a[1] = num2;
a[2] = num3;
a[3] = num4;
}
int main(){
int a[4] = {0,0,0,0};
int i;
for (i = 100000000;i<999999999;i++){
get_nums(i,a);
//去掉不必要的情况
if (all_one(a) == 0){
continue;
}
//判断是否符合要求
if(a[0] * a[1] == a[2] * a[3]){
printf("%d * %d = %d * %d\n",a[0],a[1],a[2],a[3]);
}
}
return 0;
}
最后输出结果