1 条题解

  • 0
    @ 2025-8-24 23:13:47

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar chen_kun
    生命绚烂,别被黑暗压垮。

    搬运于2025-08-24 23:13:47,当前版本为作者最后更新于2025-04-18 17:10:36,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    这道题的话主要需要一个贪心的思想。

    梳理题意


    给定 2n2n 个整数,将它们分成 nn 对,使得所有对中两数乘积的和最小。

    做法介绍


    先要总和最小,即代表每一对数中两数的乘积最小,那么肯定需要先对这些数进行排序。

    那排序后呢?我们可以试试直接将相邻的两个数配对,这样就可以使得乘积小的一组数尽量小。但是这样过于贪心了,因为这会导致成绩大的一组也过于大。

    那么我们只能折中选择一种办法:将最小的数与最大的数配对、第二小的数与第二大的数配对……以此类推,再开一个变量 ansans 累加每一对中两个数的乘积即可。

    贪心策略的证明

    设排序后数组为 a1a2...a2na₁≤a₂≤...≤a₂ₙ。根据排序不等式,a1a2n+a2a2n1+...+anan+1a₁a₂ₙ + a₂a₂ₙ₋₁ + ... + aₙaₙ₊₁ ≤ 其他任何配对方式的和。

    代码实现


    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1e5+10;
    int n,a[N*2];//有2n个数 
    int ans=0;
    signed main(){
    	cin>>n;
    	n*=2;//把n翻倍 
    	for(int i=1;i<=n;i++) cin>>a[i];
    	sort(a+1,a+n+1);//从小到大排序(从大到小排序也行) 
    	for(int i=1,j=n;i<=j;i++,j--) ans=ans+(a[i]*a[j]);//将最小的数与最大的数配对、第二小的数与第二大的数……两两配对累加起来 
    	cout<<ans;
    	return 0;
    }
    
    • 1

    信息

    ID
    12078
    时间
    2000ms
    内存
    512MiB
    难度
    2
    标签
    递交数
    0
    已通过
    0
    上传者