#CF div2 1670D Very Suspicious题解(思维+贪心)

博客探讨了一道关于无穷大正六边形棋盘的问题,通过抽象为直线交点问题,利用贪心算法求解最多可构成的三角形数。作者分享了从困惑到洞察问题本质的过程,以及如何通过数学归纳和直观理解得出解决方案。最终通过代码实现并展示了如何优化直线交点以达到最大三角形数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题链接.

1.题意:

给个无穷大的正六边形棋盘,可以画若干条过六边形对立顶点的直线,问这些直线最多可以构成多少个三角形。

2.思路:

刚看题其实自己是挺蒙的,主要由于自己总局限于六边形之中,没有跳出来,用抽象的眼光看问题。
后来在模拟中发现3点结论

  1. 直线只有3种斜率
  2. 2条斜率不同的直线,必然存在一个六边形,使得二者的交点为六边形中心
  3. 只要2条直线相交,就会产生2个三角形。(当时我从简单情况入手,在研究3条斜率不同的直线产生的三角形个数。发现当三条线交于一个六边形时,三角形个数为6;交于三个六边形时,三角形个数为3*2=6,然后突然意识到此结论是有利于解题的。还是思路和感觉吧,主要靠感觉。)

由此,我将此问题抽象为求n条直线最多交点数的问题。
然后根据贪心,可知不同斜率的直线的数量之差不得大于1,否则一定可以把较多数量的直线k1,变成较少数量的直线k2,此时交点数至少增加1(画个图就一目了然)。那么我们可以轮流将三种斜率的线画进来,得到的就是最优解。

3.代码

#include <bits/stdc++.h>
 
#define pb push_back
#define fi first
#define se second
#define mp make_pair
 
using namespace std;
 
typedef pair<int, int> PII;
typedef long long LL;
const int Mod=1e9+7,N=1e6+10;
 
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}
 
int sol(int n){
    int x = sqrt(n/6);
    int a=x*4,d=n-6*x*x;
    if(d==0)return 3*x;
    else if(a>=d)return 3*x+1;
    else if(a+a+2>=d)return 3*x+2;
    else return 3*x+3;
}
 
int main()
{
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        cout<<sol(n)<<endl;
    }
}

4.收获

  1. 此题将六边形棋盘的问题抽象为直线交点问题,无疑是一道好题
  2. 理解了一个简单的贪心模型,就是求m种斜率的直线交点个数的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值