zoukankan      html  css  js  c++  java
  • 暴力搜索+散列--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);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
  • 相关阅读:
    每日日报2021.5.14
    每日日报2021.5.13
    每日日报2021.5.12
    每日日报2021.5.11 冲刺第十天
    《梦断代码》读后感3
    每日日报2021.5.10 冲刺第九天
    《梦断代码》读后感2
    每日日报2021 5/23
    每日日报2021 5/22
    每日日报2021 5/21
  • 原文地址:https://www.cnblogs.com/sunqiangstyle/p/10312291.html
Copyright © 2011-2022 走看看