三连击问题

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

关于三连击,这是一道对新手而言不友好的题目,但是因为测试范围不是很大,我们可以直接考虑暴力解法,在1、2、3、4、5、6、7、8、9中三个一组,先看是否为1:2:3的关系,若成立,我们在利用bool数组去判断是否全部的数都出现了(也就是没有重复利用某个数),二话不说上代码!(应该最简单粗暴好理解了吧)

#include <iostream>
#include<bits/stdc++.h>//万能头文件不多BB
using namespace std;
bool a[10];
int main()
{
    int n,k,l,x1,x2,x3,y1,y2,y3,z1,z2,z3;
    for(n=123;n<987;n++)//1-9最小是123,最大是987
    {
        for(k=123;k<987;k++)
        {
            for(l=123;l<987;l++)
            {
                if(k==2*n&&l==3*n)//判断是否成立(显示问题??判断k=2n且l=3n是否成立)
                {
                    int flag=0;
                    memset(a,false,sizeof(a));//初始化数组为假
                    x1=n/100;//这个不用多说了吧,把一个三位数拆成三个数
                    y1=n/10%10;
                    z1=n%10;
                    x2=k/100;
                    y2=k/10%10;
                    z2=k%10;
                    x3=l/100;
                    y3=l/10%10;
                    z3=l%10;
                    a[x1]=true;//出现了哪个数,bool数组就记为真
                    a[x2]=true;
                    a[x3]=true;
                    a[y1]=true;
                    a[y2]=true;
                    a[y3]=true;
                    a[z1]=true;
                    a[z2]=true;
                    a[z3]=true;
                    for(int i=1;i<=9;i++)
                    {
                        if(!a[i])//只要有一个bool不为真,那么改flag
                        {
                            flag=1;
                        }
                    }
                    if(!flag)printf("%d %d %d\n",n,k,l);//如果非flag是真,那么flag没有被改(在判断里,不是0即为真),即所有数字都出现,则输出
                }
            }
        }
    }
    return 0;
}


但是很不幸,因为用了三个for循环,时间复杂度较高,就TLE了......(time limited exceeded),上一个用例时间是1092ms,这就很尴尬。 好了,既然就超限了一点,那么我们完全可以稍微改一点就成,根据我们的测试结果,可以知道,最小的满足题解数是192,最大是981,于是我们稍加改动,就可以满足时间<1000ms,改后大概700ms??(我忘了),上代码!

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
bool a[10];
int main()
{
    int n,k,l,x1,x2,x3,y1,y2,y3,z1,z2,z3;
    for(n=192;n<982;n++)
    {
        for(k=192;k<982;k++)
        {
            for(l=192;l<982;l++)
            {
                if(k==2*n&&l==3*n)//(同上,判断k=2n和l=3n是否成立)
                {
                    int flag=0;
                    memset(a,false,sizeof(a));
                    x1=n/100;
                    y1=n/10%10;
                    z1=n%10;
                    x2=k/100;
                    y2=k/10%10;
                    z2=k%10;
                    x3=l/100;
                    y3=l/10%10;
                    z3=l%10;
                    a[x1]=true;
                    a[x2]=true;
                    a[x3]=true;
                    a[y1]=true;
                    a[y2]=true;
                    a[y3]=true;
                    a[z1]=true;
                    a[z2]=true;
                    a[z3]=true;
                    for(int i=1;i<=9;i++)
                    {
                        if(!a[i])
                        {
                            flag=1;
                        }
                    }
                    if(!flag)printf("%d %d %d\n",n,k,l);
                }
            }
        }
    }
    return 0;
}


编者钟爱暴力解法,若小伙伴们觉得好理解的话,望支持!!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值