2021牛客暑期多校训练营8_K.Yet Another Problem About Pi

这篇博客探讨了一道数学与编程相结合的问题,涉及如何在无限网格中,利用一条长度为π的线段,通过一笔画路径覆盖最多的网格。作者分析了直线和斜线策略,并解释了为何在特定情况下,斜线(尤其是对角线)能够提供更高的覆盖效率。文章还提到了优化算法,如01背包问题的运用,以及特殊情况的处理。

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

Yet Another Problem About Pi

题目传送门:

题目传送门

题面:

在这里插入图片描述

题目大意:

无限多网格,长宽分别给定为 w , d w,d w,d,线的长度是pi,一笔画怎么让这条线经过的网格最多。

思路:

哎,一开始想的就是沿着直线走。
关键点在于长度为无理数,实际上从一个点出发,刚开始就有4个网格可以走到。
那么实际上就是ll ans = 4ll + ll(pi / y) * 2;
但是特殊样例:
2 2
按照以上做法答案是 6 6 6,但是实际上可以达到 7 7 7
通过走斜对角线实现。
将此作为两个操作当01背包算,因为数据水,可以枚举。

但其实还有点不懂为什么只考虑对角线,不用考虑长为 i i i格,宽为 j j j格的斜线。证明贡献为: ( i + j + 1 ) / √ ( i ∗ w ) 2 + ( j ∗ d ) 2 (i+j+1)/√(i*w)^2+(j*d)^2 (i+j+1)/(iw)2+(jd)2,可以计算出对角线的贡献最大,但是对角线的贡献在 b / a > √ 5 / 2 b/a>√5/2 b/a>5/2时候并没有直线大。

只能说似懂非懂,之后明白了再来补。

代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
double pi = acos(-1.0);

bool cmp(ll x, ll y) {
    return x > y;
}

vector<ll> ans;

int main() {
    int t;

    cin >> t;
    while (t--) {
        double w, d;
        cin >> w >> d;
        double x = sqrt(w * w + d * d);
        double y = min(w, d);

        ll ans = 4ll + ll(pi / y) * 2;
        //整条全是直线。
        ll t = 4;
        t += ll(pi / x) * 3;
        if (pi - ll(pi / x) * x >= y) t += 2;
        ans = max(t, ans);
        //先走斜线,多的走直线。

        for (int i = 0; i < 100; i++) {
            double tmp = pi - y * i;
            if (tmp < 0)break;
            ans = max(ans, 4 + ll(tmp / x) * 3 + i * 2);
            //先走直线再走斜线。
        }

        for (int i = 0; i <= 50; i++) {
            double f = pi - x * i;
            if (f < 0)break;
            ans = max(ans, 4 + ll(f / y) * 2 + i * 3);
            //先走斜线再走直线。
        }
        cout << ans << endl;
    }
}

补充

看了下有人写的题解,觉得有道理。
变换情况可能会有影响。
在这里插入图片描述
源于在这里插入图片描述

侵删。

参考了Frank_Star的博客
写出了式子:
请添加图片描述
我觉得很妙。

而且可以证明其他斜线没有对角线优,对角线好就好在可以利用最后多出来的那一部分,把直线的+2变成斜线的+3,浪费的变少了。其他情况其实不如直线+对角来的优。因为能走≥2条直线长度的话一定是走直线更优。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值