首页 > 其他分享 >洛谷题单指南-暴力枚举-P1618 三连击(升级版)

洛谷题单指南-暴力枚举-P1618 三连击(升级版)

时间:2024-01-31 10:35:45浏览次数:25  
标签:10 连击 判断 int 洛谷题 三位数 枚举 排列 P1618

原题链接:https://www.luogu.com.cn/problem/P1618

题意解读:枚举所有三位数的组合情况,判断是否符合比例。

解题思路:

方法一:枚举第一个数

根据题意,目的是寻找三个符合比例的三位数,可以直接枚举第一个,最小是123,最大是987

设第一个数为x,三个数的比例关系是a:b:c

设另外两个数为y,z

那么,根据比例关系,可以求得y = x * b / a,z = x * c / a (注意要判断a不能为0)

然后,只需要判断x,y,z三个数是否都是三位数,并且所有数字是否正好是1-9即可。

100分代码-枚举第一个数:

#include <bits/stdc++.h>
using namespace std;

int h[10];

//提取x的每个数字到桶h
void getn(int x)
{
    while(x)
    {
        h[x % 10] = 1;
        x /= 10;
    }
}

//判断x、y、z是否都是三位数,且所有数字正好包含1-9
bool check(int x, int y, int z)
{
    memset(h, 0, sizeof(h));
    if(y > 999 || y < 100 || z > 999 || z < 100) return false;
    getn(x), getn(y), getn(z);
    for(int i = 1; i <= 9; i++)
    {
        if(h[i] == 0) return false;
    }
    return true;
}

int main()
{
    int a, b, c, x, y, z, cnt = 0;
    cin >> a >> b >> c;

    for(x = 123; x <= 987; x++) //枚举第一个三位数x
    {
        if(a == 0) continue; //除数不能为0
        y = x * b / a; //根据比例计算y
        z = x * c / a; //根据比例计算z
        if(check(x, y, z)) //判断x、y、z是否有效
        {
            cout << x << " " << y << " " << z << endl;
            cnt++;
        }
    }
    
    if(!cnt) cout << "No!!!";
}

方法二:枚举排列(DFS)

要枚举所有三位数的组合情况,根据题意,可以对1-9的数字进行全排列,然后将每3个数字组成一个整数,并由小到大排列,判断是否符合比例。

时间复杂度分析:

对1-9数字进行全排列,复杂度为9!,可以直接写段代码计算:

int ans = 1;
for(int i = 1; i <= 9; i++)
{
   ans *= i;
}
cout << ans; // 输出:362880

对每一组排列进行数字提取、3个数排序等操作,复杂度小于10,总体复杂度在百万级别,因此不会超时。

当找到一组排列,按照每三位数字组成一个整数,得到三个整数,由小到大排序;

再判断三个整数是否符合比例关系,如果要判断x、y、z三个数是否符合a:b:c,只需要判断x * b == y * a && y * c == z * b是否成立即可。

另外,需要注意,全排列组成的三位数中,会出现重复情况,如123/456/789和789/456/123三个数由小到大排序后是一样的,因此需要去重。

去重很显然要借助hash,可以将三个数拼接在一起,判断是否出现过即可,由于拼接后最长有9位数,如果用数组则要开109的空间,可能爆内存,

而所有9个数的排列一共只有36万多,因此用map。

100分代码-DFS:

#include <bits/stdc++.h>
using namespace std;

int tmp[10];
bool flag[10], yes;
int res[5];
map<int, int> h;

int a, b, c;

void dfs(int k)
{
    if(k == 10) //当找到一个排列
    {
        for(int i = 1; i <= 3; i++) //按照每三个数字组成一个整数,填入res数组
            res[i] = tmp[(i - 1) * 3 + 1] * 100 + tmp[(i - 1) * 3 + 2] * 10 + tmp[(i - 1) * 3 + 3];
        sort(res + 1, res + 4); //将三个整数排序
        if(res[1] * b == res[2] * a && res[2] * c == res[3] * b) //判断是否符合a:b:c
        {
            int value = res[1] * 1000000 + res[2] * 1000 + res[3];
            if(!h[value]) //判断三个数字是否已经出现过,因为排列会导致重复,如123,456,789和456,123,789是一样的
            {
                cout << res[1] << " " << res[2] << " " << res[3] << endl;
                yes = true; //yes=true说明找到了一组结果
                h[value] = 1;
            }
        }    
    }

    for(int i = 1; i <= 9; i++) // 枚举1-9的全排列
    {
        if(!flag[i])
        {
            flag[i] = true;
            tmp[k] = i; //数据存入tmp
            dfs(k + 1);
            flag[i] = false;
        }
    }
}

int main()
{
    cin >> a >> b >> c;
    dfs(1);
    if(!yes) cout << "No!!!";
}

 

标签:10,连击,判断,int,洛谷题,三位数,枚举,排列,P1618
From: https://www.cnblogs.com/jcwy/p/17998675

相关文章

  • 洛谷题单指南-暴力枚举-P2241 统计方形(数据加强版)
    原题链接:https://www.luogu.com.cn/problem/P2241题意解读:要在整个n*m区域计算正方形和长方形的个数,枚举法即可。解题思路:此题枚举的对象是矩形的高i和宽j,高的范围[1,n],宽的范围[1,m],然后计算在n*m区域内有多少个i*j,i==j即属于正方形,i!=j属于长方形。那么,问题就集中在了......
  • 洛谷题单指南-排序-P1012 [NOIP1998 提高组] 拼数
    原题链接:https://www.luogu.com.cn/problem/P1012题意解读:通过某种合理的排序方式,使得排序后的数字连在一起最大。解题思路:此题关键在于排序,对于两个数字,哪个数字应该排在前面呢?1、思考误区很容易想到,给定两个数abcd、xyz,先比较第一位a和x,谁大谁排前面,一直到c和z。再来看d,这......
  • 洛谷题单指南-排序-P1104 生日
    原题链接:https://www.luogu.com.cn/problem/P1104题意解读:将学生按照年龄由大到小排序,如果年龄相同,后输入的排在前面,输出排序后的学生姓名。解题思路:此题是一个排序常规题,年龄大排在前说明年、月、日越小越在前面,核心的排序思路如下:1、如果年份不同,按年份由小到大排序2、如果......
  • 洛谷题单指南-排序-P5143 攀爬者
    原题链接:https://www.luogu.com.cn/problem/P5143题意解读:给出一系列的点,按某种顺序经过所有点,计算距离。解题思路:如果小学生,可能对于三维坐标距离有些陌生,没关系,题目已经给出了计算公式,直接套公式即可,关键步骤如下:1、读取所有坐标点2、按高度值从小到大排序3、从头依次计算......
  • 洛谷题单指南-排序-P1068 [NOIP2009 普及组] 分数线划定
    原题链接:https://www.luogu.com.cn/problem/P1068题意解读:根据题意,用模拟法,求出分数线所在位置,然后计算分数线,最后输出结果即可。解题思路:1、分数线是按从大到小排名来设定,因此数据因为按照分数从大到小排序,如果分数相同,需要安装报名号从小到大排序2、计算分数线位置,主要是下......
  • 洛谷题单指南-排序-P1152 欢乐的跳
    原题链接:https://www.luogu.com.cn/problem/P1152题意解读:要判断相邻数差的绝对值是否覆盖1~n-1,只需遍历相邻两数之差,借助数组标记差的绝对值是否存在,然后遍历数组即可。解题思路:此题有两个注意点:1、数值要用longlong2、计算差值绝对值后,标记桶数组时,有可能导致越界,因为每个......
  • 洛谷题单指南-排序-P2676 [USACO07DEC] Bookshelf B
    原题链接:https://www.luogu.com.cn/problem/P2676题意解读:要使能够到书架顶的牛数量最少,优先选高的牛即可,直到总身高超过书架高度,简单的排序+贪心,下面给出代码。100分代码:#include<bits/stdc++.h>usingnamespacestd;constintN=20005;inth[N];intn,b;intmain......
  • 洛谷题单指南-排序-P1781 宇宙总统
    原题链接:https://www.luogu.com.cn/problem/P1781题意解读:题目思路非常简单,在n个投票数中选最大的,并记录其编号即可,由于投票数很大,无法直接用整形,需要通过string来进行数字比较。解题思路:本题的关键在于如何比较string数字的大小?在高精度减法时,需要判断两个数的大小,用大数减小......
  • 洛谷题解-[ABC286E] Souvenir
    https://www.luogu.com.cn/problem/AT_abc286_e题目描述NNN個の都市があり、いくつかの相異なる都市の間は一方通行の直行便によって移動することができます。どの直行便が存在するかはNNN個の長さNNNの文字列S1,S2,…,SNS_1,S_2,\ldots,S_NS1​,S2​,…,SN​......
  • 洛谷题解-[ABC325E] Our clients, please wait a moment
    https://www.luogu.com.cn/problem/AT_abc325_e题目描述ある国には都市がNNN個あります。あなたは、都市111にある営業所から000個以上の都市を経由して都市NNNにある訪問先へ移動しようとしています。移動手段は社用車と電車の222種類があります。都市......