暴力搜索+散列--P1008 三连击

题目描述

将1,2, ⋯,9共9个数分成3组,分别组成3个三位数,且使这3个三位数构成1:2:3的比例,试求出所有满足条件的3个三位数。

输入输出格式

输入格式:
木有输入

输出格式:

若干行,每行3个数字。按照每行第1个数字升序排列。

输入输出样例

输入样例#1:

输出样例#1:

192 384 576

(输出被和谐了)

分析:

题意为输出3个三位数,如何将所有的三位数罗列出来?只用一个for循环生成三个排列的数不简单,可以考虑使用三个for循环,按照百位、十位、个位拼接成三位数。仅仅得到一个三位数如何找到另外两个三位数呢?题意说明1-9各用一次,正面求解不方便可以直接将得到的三位数乘以2,乘以3,判断是否9个数字全部用上

int main() {
    for (int i = 1; i <= 9; ++i) {
        for (int j = 0; j <= 9; ++j) {
            for (int k = 0; k <= 9 ; ++k) {
                int a = i*100+j*10+k;
                int b = a*2;
                int c = a*3;
                if(b>999||c>999)continue;
                nums[i]=1;
                nums[j]=1;
                nums[k]=1;
                nums[b/100]=1;
                nums[(b/10)%10]=1;
                nums[b%10]=1;
                nums[c/100]=1;
                nums[(c/10)%10]=1;
                nums[c%10]=1;
                if(nums[1]==1&&nums[2]==1&&nums[3]==1&&nums[4]==1&&nums[5]==1&&nums[6]==1&&nums[7]==1&&nums[8]==1&&nums[9]==1)
                    printf("%d %d %d 
",a,b,c);
                  for (int l = 0; l < 10; ++l) {
                      nums[l] = 0;
                  }
            }
        }
    }
    return 0;
}

简单优化:

void sanlie(int no){
    while (no!=0){
        nums[no%10]=1;//取最后一位,做散列查表
        no/=10;//消除最后一位
    }
}
int main() {
    for (int i = 1; i <= 9; ++i) {
        for (int j = 0; j <= 9; ++j) {
            for (int k = 0; k <= 9 ; ++k) {
                int a = i*100+j*10+k;
                int b = a*2;
                int c = a*3;
                if(b>999||c>999)continue;
                sanlie(a);
                sanlie(b);
                sanlie(c);
                if(nums[1]==1&&nums[2]==1&&nums[3]==1&&nums[4]==1&&nums[5]==1&&nums[6]==1&&nums[7]==1&&nums[8]==1&&nums[9]==1)
                    printf("%d %d %d 
",a,b,c);
                memset(nums,0, sizeof(nums));
            }
        }
    }
    return 0;
}

学到的点:
1、使用百位+十位+个位的方式构造数值
2、使用memset()重置数组,比for循环高效
3、使用数值中出现的数字作为数组的下标,表示是否出现(散列法、查表法),第一次的想法为利用数组存放三个三位数出现的数字,下标为自然0-9,需要比较各不相同(1,2…9),相比散列只需比较是否出现(为1)
4、求数组长度sizeof(nums)/ sizeof(nums[0]),sizeof求得是字节长度(下面的例子)


不太懂循环怎么写,于是尝试了下:
void xunhuan() {
    for (int i = 1; i < 10; ++i) {
        for (int j = 1; j < 10; ++j) {
            for (int k = 1; k < 10; ++k) {
                for (int l = 1; l < 10; ++l) {
                    for (int m = 1; m < 10; ++m) {
                        for (int n = 1; n < 10; ++n) {
                            for (int i1 = 1; i1 < 10; ++i1) {
                                for (int j1 = 1; j1 < 10; ++j1) {
                                    for (int k1 = 1; k1 < 10; ++k1) {
                                        int a = i * 100 + j * 10 + k;
                                        int b = l * 100 + m * 10 + n;
                                        int c = i1 * 100 + j1 * 10 + k1;
                                        int nums[10] ={i,j,k,l,m,n,i1,j1,k1};
                                        int flag = 1;
                                        for (int l1 = 0; l1 < sizeof(nums)/ sizeof(nums[0]); ++l1) {
                                            for (int m1 = l1+1; m1 < sizeof(nums)/ sizeof(nums[0]); ++m1) {
                                                if(nums[m1]==nums[l1]) {
                                                    flag=0;
                                                    break;
                                                }
                                            }
                                            if(flag == 0)break;
                                        }
                                        if (a * 2 == b && a * 3 == c && b < 1000 && c < 1000&&flag) {
                                            printf("%d %d %d 
", a, b, c);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
原文地址:https://www.cnblogs.com/sunqiangstyle/p/10312291.html