zoukankan      html  css  js  c++  java
  • 洛谷 P1618 三连击(升级版)【DFS/next_permutation()/技巧性枚举/sprintf】

    【链接】:https://www.luogu.org/problemnew/show/P1618

    题目描述

    将1,2,…,9共9个数分成三组,分别组成三个三位数,且使这三个三位数的比例是A:B:C,试求出所有满足条件的三个三位数,若无解,输出“No!!!”。

    //感谢黄小U饮品完善题意

    输入输出格式

    输入格式:

    三个数,A B C。

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    1 2 3
    输出样例#1: 复制
    192 384 576
    219 438 657
    273 546 819
    327 654 981

    说明

    保证A<B<C

    【分析】:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int main(){
        int a,b,c,num,i1,i2,i3,flag=0;
        cin>>i1>>i2>>i3;
        for(num=1;num<=999;num++){
            a=i1*num;b=i2*num;c=i3*num;
            if((a/100+a/10%10+a%10+b/100+b/10%10+b%10+c/100+c/10%10+c%10==45)&&((a/100)*(a/10%10)*(a%10)*(b/100)*(b/10%10)*(b%10)*(c/100)*(c/10%10)*(c%10)==362880)){
                cout<<a<<" "<<b<<" "<<c<<endl;
                flag=1;
            }    
        }
        if(flag==0){
            cout<<"No!!!";
        }
        return 0;
        
    } 
    普通枚举

    1.

    枚举每一个可能的数,将三个倍数保存在数组中,再排序,最后通过和标准的“123456789”比较,如果相同,则满足条件。这样用一个常量数组,可以简化计算,不需要过多的思考。所以说常量数组大法真的好~因为之前做过三连击的简单版,就有了思维定式,枚举总是从123开始,所以最后一个(数据是123 456 789)总是错。最后一个过不去的同学可以试试从1开始枚举,就会过去了。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    char stdanard[]="123456789";
    
    int a,b,c;
    
    int main()
    {
        int flag=1;
        cin>>a>>b>>c;
        for(int i=1;i<=999;i++)
        {
            char buf[20];//开大防止溢出
            sprintf(buf,"%d%d%d",a*i,b*i,c*i);
            sort(buf,buf+9);
            if(strcmp(stdanard,buf)==0)
            {
                flag=0;
                printf("%d %d %d
    ",a*i,b*i,c*i);
            }
        }
        if(flag) puts("No!!!");
        return 0;
    }
    sprintf

    2.我和大部分人思路基本一样,不一样的地方在于对三个数组成的9个数的拆分上,我用的是sstream头文件,将三个数放到一个字符串中去,这样就不用%或者/去费力拆分了,写起来更优雅,然后将字符串每个数加起来 乘起来,即可验证是否为不同的9个数。

    /*
    对三个数组成的9个数的拆分上,用的是sstream头文件,
    将三个数放到一个字符串中去,
    这样就不用%或者/去费力拆分了,写起来更优雅,
    然后将字符串每个数加起来 乘起来,即可验证是否为不同的9个数。
    */
    #include <bits/stdc++.h>
    
    using namespace std;
    
    stringstream ss;
    string str;
    int cnt=0;
    int a,b,c;
    
    int main()
    {
        cin>>a>>b>>c;
    
        for(int i=123;i<=329;i++)
        {
            int j=i*b/a;
            int k=i*c/a;
            int sum=0;
            int pro=1;
            ss<<i<<j<<k;
            ss>>str;
            ss.clear();
    
            for(int j=0;j<9;j++)
            {
                sum+=str[j]-'0';
                pro*=str[j]-'0';
            }
    
            if(sum==45 && pro==362880)
            {
                cout<<i<<" "<<j<<" "<<k<<" "<<endl;
                cnt++;
            }
    
        }
        if(!cnt) puts("No!!!");
        return 0;
    }
    stringstream

    3.

    /*
    其实判断是否相等不需要if(a==b&&b==c...)这样乱七八糟的打一大坨,一个数组就能完成。如下:
    */
    #include <bits/stdc++.h>
    
    using namespace std;
    
    int d[10];//数组d判断位数是否相等。
    int main()
    {
        float x,y,z;
        int a,b,c,t=0,j=0;//j判断是否有解
        cin>>x>>y>>z;//即A、B、C
        for(a=100;a<=999;a++)//枚举最小的那个数
        {
            b=y*a/x;
            c=z*a/x;
            d[a/100]++;
            d[(a%100)/10]++;
            d[a%10]++;
            
            d[b/100]++;
            d[(b%100)/10]++;
            d[b%10]++;
            
            d[c/100]++;
            d[(c%100)/10]++;
            d[c%10]++;
            for(int bb=1;bb<=9;bb++)
            {
                if(d[bb]==0) t=1;//由于总共只有九个数字,若有一个数没有出现,就说明有数字重复了。
                d[bb]=0;//归零
            }
            if(t==0) {cout<<a<<" "<<b<<" "<<c<<endl;j=1;}//若有解,输出a、b、c
            t=0;
        }
        if(!j) cout<<"No!!!";
        return 0;
    }
    数组技巧性枚举
    # include <stdio.h>
    # define MUL(x) (x%10)*(x/10%10)*(x/100)            //一个三位数x所包含的3个数的乘积为MUL(x)
    # define ADD(x) (x%10)+(x/10%10)+(x/100)            //一个三位数x所包含的3个数的总和为ADD(x)
    const product=1*2*3*4*5*6*7*8*9;                    //数字1—9的乘积为product
    const int sum=1+2+3+4+5+6+7+8+9;                    //数字1—9的总和为sum
    int main()
    {
        int A,B,C,a=0,Yes=0;                            //变量Yes用于检测是否有解
        scanf("%d %d %d",&A,&B,&C);                        //输入3个三位数的比例A:B:C(A<B<C且为最简比)
        while(++a*A<100);                                //保证这3个数中最小的数是三位数
        for(;a*C<1000;a++)                                //保证这3个数中最大的数是三位数
            if(product==MUL(a*A)*MUL(a*B)*MUL(a*C)        //倘若它们所包含的9个数的乘积恰好为product
                && sum==ADD(a*A)+ADD(a*B)+ADD(a*C))        //并且总和恰好为sum时,说明没有重复数字和0
                Yes=printf("%i %i %i
    ",a*A,a*B,a*C);    //输出这3个由1—9组成的三位数,并给Yes赋值
        if(!Yes)                                        //若无解
            puts("No!!!");                                //则输出“No!!!”
        return 0;
    }
    技巧性枚举

    4.

    #include<iostream>
    using namespace std;
    int x[10]={0},a,b,c; //x[1]~x[9]为当前位置的数字 先把三个三位数合成一个9(10)位数的大数组
    bool used[10]={0},ans=false;
    //used数组表示该数字的使用情况 避免重复   ans判断是否有答案
    int cons(int m){   //将数组拆分成三个三位数
        int sum=0;
        for(int i=3*m-2;i<=3*m;i++){
            sum*=10;
            sum+=x[i];
        }
        return sum;
    }
    void solve(int n){
        if(n==10&&cons(1)*b==cons(2)*a&&cons(1)*c==cons(3)*a){   //当n=10时x数组数字存满 开始判断
            cout<<cons(1)<<" "<<cons(2)<<" "<<cons(3)<<endl;
            ans=true;
            return;
        }
        for(int i=1;i<=9;i++){
            if(!used[i]){
                x[n]=i;   //存数字
                used[i]=1;   //该数字被使用
                solve(n+1);  //下一位继续调用
                used[i]=0;  //恢复
            }
        }
        return;
    }
    int main(){
        cin>>a>>b>>c;
        solve(1);  //开始搜索
        if(!ans) cout<<"No!!!";  //ans!=true即输出"No!!!"
        return 0;
    }
    DFS

    5.STL中的next_permutation函数提供下一个排列功能,是用生成法实现的,所以速度要比搜索快多了。

    #include<bits/stdc++.h>
    using namespace std;
    int a[10]={0,1,2,3,4,5,6,7,8,9};
    int main()
    {
        int A,B,C,h=0;
        cin>>A>>B>>C;
        int t=A*B*C;
        A=t/A;
        B=t/B;
        C=t/C;
        do{
            if((100*a[1]+10*a[2]+a[3])*A==(100*a[4]+10*a[5]+a[6])*B&&(100*a[1]+10*a[2]+a[3])*A==(100*a[7]+10*a[8]+a[9])*C)//如果符合比例;
            {
                cout<<a[1]<<a[2]<<a[3]<<" "<<a[4]<<a[5]<<a[6]<<" "<<a[7]<<a[8]<<a[9]<<endl;//输出
                h++;
            }
        }while(next_permutation(a+1,a+10));//STL中的下一个排列函数;
        if(h==0) cout<<"No!!!";//没有解输出NO;
        return 0;
    }
    next_permutation()
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int a[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    bool isSame(int v[], int a[]) {
        for (int i = 0; i != 3; i++)
            if (v[i] != a[i])
                return false;
        return true;
    }
    int main()
    {
        int A, B, C;
        int visit[3] = { 0 };
        int pos;
        bool flag = false;
        cin >> A >> B >> C;
        do {
            int x = a[0] * 100 + a[1] * 10 + a[2];
            int y = a[3] * 100 + a[4] * 10 + a[5];
            int z = a[6] * 100 + a[7] * 10 + a[8];
            int a[3] = { x, y, z };
            sort(a, a + 3);
            if (!isSame(visit, a)) {
                if ((double)y / x == (double)B / A && (double)z / x == (double)C / A && (double)z / y == (double)C / B) {
                    cout << a[0] << " " << a[1] << " " << a[2] << endl;
                    flag = true;
                }
            }
        } while (next_permutation(a, a + 9));
        if (flag == false)
            cout << "No!!!" << endl;
        return 0;
    }
    5.2
  • 相关阅读:
    组播IP地址
    改变未来的10大科技
    知行合一之健康
    2017第47周五
    2017第47周四感恩节
    spring boot测试
    2017第47周二
    音频格式opus
    周日反思
    四种人工智能技术对五个行业的影响
  • 原文地址:https://www.cnblogs.com/Roni-i/p/8277327.html
Copyright © 2011-2022 走看看