大暴力 Function

本文介绍了一种通过优化暴力算法来解决特定数学问题的方法。重点在于如何通过减少不必要的计算步骤提高效率,并利用一次函数的特性来简化求解过程。

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

  

问题 C: Function

时间限制: 2 Sec   内存限制: 512 MB
提交: 76   解决: 49
[ 提交][ 状态][ 讨论版]

题目描述

        正解是估值线段树。。我不会。。。QAQ,我只会打暴力,而且这道题成功虐了出题人智商,优化一下暴力就能A。 思路就是求解多于范围。所以记录每个访问点的值,如果再访问,直接输出就行。注意会卡常数。
       我联考时还是打了点有思维含量的东西的。就是3~6这三个点,只是一次函数,单调的。求每个交点,更新每条直线是总体最大值的区间。两个优化。1,左端点大于右端点过掉。2,交点不一定是整数,所以要调整交点的值。(这个貌似不是优化)记录询问区间里每个点对应的最大值函数的下标。。
       联考时被卡常了QAQAQAQ
     
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1000000000
using namespace std;
inline ll read()
{
  ll x=0,f=1;char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}
struct qj
{
    int l,r;
} f[1005];
int n,q,p=0,v[1005];
ll a[1005],b[1005],c[1005];
ll hz[200204],cun[200205];
inline ll get(int i,int x)
{
    return a[i]*x*x+b[i]*x+c[i];
}
void init()//唯一不是暴力的地方。。。
{
    for(int i=1;i<=n;i++){f[i].l=-100000;f[i].r=100000;}
    for(int i=1;i<=n;i++)
       for(int j=i+1;j<=n;j++)
           if(!v[i]&&!v[j])
           {
                if(b[i]==b[j])
                {
                    if(c[i]>=c[j])v[j]=1;
                    else v[i]=1;
                    continue;
                }
                if(b[i]>b[j])
                {
                    int x=(c[j]-c[i])/(b[i]-b[j]);
                    int a1=get(i,x),a2=get(j,x);
                    if(a1==a2)
                    {
                        if(x>f[i].l)f[i].l=x;if(x>f[i].r)v[i]=1;
                        if(f[j].r>x)f[j].r=x;if(x<f[j].l)v[j]=1;
                    }
                    else
                    {
                         int x1=x,x2=x;
                         if(a1<a2)x1++;
                         else x2--;
                         if(x1>f[i].l)f[i].l=x1;if(x1>f[i].r)v[i]=1;
                        if(f[j].r>x2)f[j].r=x2;if(x2<f[j].l)v[j]=1;
                    }
                }
                else
                {
                    int x=(c[j]-c[i])/(b[i]-b[j]);
                    int a1=get(i,x),a2=get(j,x);
                    if(a1==a2)
                    {
                        if(x>f[j].l)f[j].l=x;if(x>f[j].r)v[j]=1;
                        if(f[i].r>x)f[i].r=x;if(x<f[i].l)v[i]=1;
                    }
                    else
                    {
                         int x1=x,x2=x;
                         if(a1<a2)x1--;
                         else x2++;
                         if(x2>f[j].l)f[j].l=x2;if(x2>f[j].r)v[j]=1;
                         if(f[i].r>x1)f[i].r=x1;if(x1<f[i].l)v[i]=1;
                    }
                }
           }
    for(int i=1;i<=n;i++)
       if(!v[i])
       {
         for(int j=f[i].l;j<=f[i].r;j++)
             cun[j+100005]=i;
        }
}
int main()
{
    //freopen("function.in","r",stdin);
    //freopen("function.out","w",stdout);
    n=read();q=read();
    for(int i=1;i<=n;i++)
    {
        a[i]=read();if(a[i]!=0)p=1;
        b[i]=read();
        c[i]=read();
    }
    int x;ll sum=-inf;
    if(!p)
    {
        init();
        while(q--)
        {
            x=read();
            int i=cun[x+100005];
            sum=a[i]*x*x+b[i]*x+c[i];
            printf("%lld\n",sum);
        }
    }
    else
    {
        while(q--)
        {
            x=read();sum=-inf;
            if(hz[x+100005])
                printf("%lld\n",hz[x+100005]);
            else
            {
                for(int i=1;i<=n;i++)
                {
                    ll k=a[i]*x*x+b[i]*x+c[i];
                    if(sum<k)sum=k;
                }
                hz[x+100005]=sum;
                printf("%lld\n",sum);
            }
             
        }
    }
}

### 如何优化暴力模拟算法以避免超时 在解决像LeetCode5707这样的问题或其他类似的组合优化问题时,如果采用暴力模拟的方法可能会遇到时间复杂度过高的情况。为了减少计算量并提高效率,可以考虑以下几种优化方式: #### 1. 使用启发式搜索代替完全枚举 启发式搜索能够显著降低搜索空间小。例如,在某些情况下可以通过贪心策略先找到一个较优解作为初始状态,再利用改进版的局部搜索技术进一步提升结果质量。这种方法虽然不一定能找到绝对意义上的全局最优解,但在很多实际应用场景下已经足够接近理想答案。 #### 2. 应用剪枝技巧缩小候选集合范围 当遍历所有可能性时加入条件判断提前终止无意义分支的操作称为剪枝。具体来说就是在每一步决策之前评估当前路径是否有潜力成为最终解答的一部分;如果没有,则立即停止对该方向继续探索。这样做的好处是可以极地削减不必要的运算次数[^1]。 #### 3. 转向更高效的元启发式算法如模拟退火法 正如前面提到过的内容那样,模拟退火是一种非常有效的随机化搜索手段之一。它模仿自然界中金属冷却结晶的过程来寻找问题的最佳解决方案。相比单纯的穷尽尝试而言,该方法允许一定程度上的“错误”移动——即使新状态比旧的状态差也有可能接受这种变化,这有助于逃离局部最优点而趋向整体最值或者最小值位置附近区域进行深入考察。 以下是基于Python实现的一个简单版本模拟退火伪代码示例: ```python import random import math def simulated_annealing(initial_state, cost_function, neighbor_function, temperature_decay_rate=0.99, initial_temperature=1000, stopping_temperature=1e-8): current_state = initial_state best_state = current_state current_cost = cost_function(current_state) best_cost = current_cost temperature = initial_temperature while temperature > stopping_temperature: next_state = neighbor_function(current_state) next_cost = cost_function(next_state) delta_e = next_cost - current_cost if delta_e < 0 or random.uniform(0, 1) < math.exp(-delta_e / temperature): current_state = next_state current_cost = next_cost if current_cost < best_cost: best_state = current_state best_cost = current_cost temperature *= temperature_decay_rate return best_state, best_cost ``` 此函数接收五个主要参数:起始状态`initial_state`, 计算成本/适应度得分的功能`cost_function`, 定义邻居节点选取逻辑的方式`neighbor_function`, 温度衰减因子以及初始化和结束温度设定值。通过调整这些配置项可以让程序更好地适配不同种类的问题需求场景。 综上所述,针对暴力模拟容易造成运行耗时过多的现象,我们既可以采取针对性强的技术改造措施比如合理运用剪枝机制,也可以选用更加高级别的智能化求解框架例如模拟退火等来进行替代升级操作^。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值