洛谷--【P1618】三连击升级版题解 排列枚举+循环枚举+stl

题目描述

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

输入格式

三个数,A,B,C。

输出格式

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

输入输出样例

输入 #1
1 2 3
输出 #1192 384 576
219 438 657
273 546 819
327 654 981

题意解析:
根据题目要求不难发现题目想让我们在1-9九个数字数字中选择数字随机组合成三个数字使其比例成A:B:C,这样的三个不同的三位数组成一组数,把满足条件的所有组输出。三个数字一行。
下面通过代码来实现。
解法一(排列枚举+stl)
全ac代码如下:

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int a[10];
int main(){
    long long A,B,C,x,y,z;
    cin>>A>>B>>C;int cnt=0;
    for(int i=1;i<=9;i++){
        a[i]=i;
    }
    do{
        x=a[1]*100+a[2]*10+a[3];
        y=a[4]*100+a[5]*10+a[6];
        z=a[7]*100+a[8]*10+a[9];
        if(x*B==y*A&&y*C==z*B){
            printf("%lld %lld %lld\n",x,y,z);
            cnt++;
        }
    }while(next_permutation(a+1,a+10));
    if(!cnt) cout<<"No!!!";
}

浅析代码:顺着题目意思来我们可以把所有的符合条件的三位数进行枚举,再加上一个条件判断是否成比例即可。这里介绍stl标准库中很好用的一个标准函数next_permutation(start,end),其功能就是在[start,end)数组中产生严格的下一个字典序排列。因此我们可以初始化一个长度为10的数组,通过遍历将所有三位数枚举出来。这样再通过条件判断后就可以得到最后的答案了。

解法二:子集枚举

代码如下:

#include<iostream>
 using namespace std;
 #include<cstdio>
 #include<algorithm>
 #include<cstring>
 int b[10];
 bool check(int a,int b,int c);
 void allocate(int a);
 bool check(int x,int y,int z){
 memset(b,0,sizeof(b));
 if(y>999||z>999) return 0;
 allocate(x);allocate(y);allocate(z);
 for(int i=1;i<=9;i++){
 if(!b[i]) return 0;
 }
 return 1;
 }
 void allocate(int a){//将每一位数分配到桶中
 b[a%10]=1;
 b[a/10%10]=1;
 b[a/100]=1;
 }
 int main(){
 int A,B,C,i,y,z,cnt=0;cin>>A>>B>>C;
 for( i=123;i<=987;i++){
 if(i*B%A||i*C%A) continue;//先找到数i
 y=i*B/A,z=i*C/A;//再确定按比例分配的另外两个
 if(check(i,y,z))
 printf("%d %d %d\n",i,y,z),cnt++;
 }
 if(!cnt) puts("No!!!");
 return 0;
 }

 浅析代码:总的来说,这段代码不够简洁,而且如果这题求的是多位数可能就会比较繁琐,并且我在洛谷平台提交这段代码测评的时候在新上传的用例中有一个案例re了。基于其它案例顺利通过以及这种做法所蕴含的思想,我们也对这段代码进行解析,仅供参考。首先可以确定三位数的范围在123-987之间,因此可以先遍历这些数字,找到第一个满足条件的数字,进而算出另外两个数字。但是由于这个范围内一定存在含有0的三位数字,所以要进行判断。因此将所得的三个数字x,y,z传入check函数中,在check函数中再将三位数进行分解,这里写的allocate函数,由于下标为零的数组未被赋值所以为零,这样便可以区分0和非0数,检查若为真则计数器加一否则输出No!!!,最后得出正确答案。

 

 

posted @ 2022-11-07 22:53  curtain_cpp  阅读(333)  评论(0)    收藏  举报