蓝桥杯这题怎么解

童话的守望者 2016-03-08 03:50:03

问题描述
  给n个有序整数对ai bi,你需要选择一些整数对 使得所有你选定的数的ai+bi的和最大。并且要求你选定的数对的ai之和非负,bi之和非负。
输入格式
  输入的第一行为n,数对的个数
  以下n行每行两个整数 ai bi
输出格式
  输出你选定的数对的ai+bi之和
样例输入
5
-403 -625
-847 901
-624 -708
-293 413
886 709
样例输出
1715
数据规模和约定
  1<=n<=100
  -1000<=ai,bi<=1000
...全文
967 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
兔老大RabbitMQ 2018-12-12
  • 打赏
  • 举报
回复
摔手机最优解https://blog.csdn.net/hebtu666/article/details/84789853
fesdobat 2017-01-13
  • 打赏
  • 举报
回复
首先不管递归也好循环也好,它本质上等于一个2的n次方的枚举暴力破解。如果n=100,所需时间就是天文数字了。 所以这类题的要点是通过各种优化和算法,降低需要枚举的次数,也就是n的值。 我的解题思路: 对这道题来说,首先可以排除的是a,b都是负数的对。(很简单的证明,这里就不啰嗦了) 同理可得,a,b都是正的对必然会出现在最终结果中,这样的对也可以预先排除。 为阐述方便先引入两个名词:把a+b的值称为利益,把数对的a之和称为左配平,数对的b之和称为右配平。 剩下的对可分为4类: A 左正右负利益为正;B 左负右正利益为正; C 左正右负利益为负;D 左负右正利益为负; 如果不考虑配平,A+B就是能实现利益最大化的方案。 真正的解题从这里开始。我们以A+B为基础做减法。考虑A+B的配平: ①左右皆正:皆大欢喜。这正是我们要的最终答案。 ②有一个为负。则另一个必然为正。(两边都负是不可能的,请自行证明) 对于②,这是我们要解决的问题。假设是左配平为负,右配平为正。 这里开始用枚举试探法。往当前结果中插入C类数对,看是否能把左配平加到正。 这个试探过程有4个要点: ①同时要保证右配平不能为负; ②按照负利益的绝对值从小到大的顺序进行测试; ③C中任意项组成的“负利益组”,也要加入测试; ④考虑到去除B类数对能起到同样的效果,要把B反转加入C 所以到这里,问题的核心变成了“对集合C={c1,c2,c3……cn,{Σ任意c之和} },如何从小到大遍历它”。 注意集合C的大小为2的n次方,如果数据比较针对,n任然有为100的可能。 如果先计算出所有C的元素,再排序,再遍历,时间复杂度还是2的n次方,不可取。 在我的思路中,这里成为了整个题目的核心。 对此我想出的方法是“增量构造递增序列法”。 思路就是先构造几个最小值,并对他们进行测试。如果通过,则问题解决; 如果不通过,则再构造下几个次小值,再进行测试。循环往复直到测试成功。 目前我只对理想化的情况(C中没有重复元素)写了算法,并打算到此做一段落了。 当然我这个“增量构造递增序列法”肯定不是最优的, 如果楼主能理解并同意我的思路,一定能找出更好的算法。
lunat 2017-01-11
  • 打赏
  • 举报
回复
确实是背包问题。试下这样。

#include <cstdio>

typedef struct {
    int a, b;
} data_t;

int max_sum(data_t * data, int n, int min_sum_a, int min_sum_b) {
    if (n == 0) { 
        return (data[0].a >= min_sum_a && data[0].b >= min_sum_b) ? data[0].a + data[0].b : 0; 
    }

    int m_1 = max_sum(data, n - 1, min_sum_a, min_sum_b);
    int m_2 = max_sum(data, n - 1, min_sum_a - data[n].a, min_sum_b - data[n].b) + data[n].a + data[n].b;

    return m_1 > m_2 ? m_1 : m_2;
}

int main() {
    int n;
    data_t data[100];

    scanf("%d", &n);

    for (int i = 0; i < n; ++i) {
        scanf("%d %d", &data[i].a, &data[i].b);
    }

    printf("%d\n", max_sum(data, n, 0, 0) );
    return 0;
}
sinat_34721511 2017-01-10
  • 打赏
  • 举报
回复
data[i]=dataB[i].ai+dataB[i].bi;//data[i]为ai、bi之和
错的 他连题都没读懂
我用递归会超过时间要求
应该是背包问题 但想不出这么写
仙境之桥2046 2016-03-15
  • 打赏
  • 举报
回复
引用 3 楼 yuelengdihai 的回复:
[quote=引用 2 楼 yiduiguwen 的回复:] [quote=引用 1 楼 yuelengdihai 的回复:]

struct  Data
{
    int  ai;
    int   bi;
}dataB[20];//结构体数组

@yuelengdihai 可是那然后呢?这题的递推公式怎么解[/quote]

int data[20];
for(int i=0;i<n;i++)
{
     data[i]=dataB[i].ai+dataB[i].bi;//data[i]为ai、bi之和
}

如果有需要就根据ai、bi值进行排序
data[]数组中最大值取出来输出就可以了
[/quote] 不用排序吧,直接加个值不久可以了么
cocoabird 2016-03-10
  • 打赏
  • 举报
回复
引用 4 楼 yiduiguwen 的回复:
[quote=引用 3 楼 yuelengdihai 的回复:] [quote=引用 2 楼 yiduiguwen 的回复:] [quote=引用 1 楼 yuelengdihai 的回复:]

struct  Data
{
    int  ai;
    int   bi;
}dataB[20];//结构体数组

@yuelengdihai 可是那然后呢?这题的递推公式怎么解[/quote]

int data[20];
for(int i=0;i<n;i++)
{
     data[i]=dataB[i].ai+dataB[i].bi;//data[i]为ai、bi之和
}

如果有需要就根据ai、bi值进行排序
data[]数组中最大值取出来输出就可以了
[/quote]m没有看懂精华呀,烦请再解释一下[/quote] data[i]是一个结构体数组,里面存储第i组数据ai、bi值 首先要对每组数据的ai、bi进行赋值 然后就是基本的逻辑处理了
童话的守望者 2016-03-10
  • 打赏
  • 举报
回复
引用 3 楼 yuelengdihai 的回复:
[quote=引用 2 楼 yiduiguwen 的回复:] [quote=引用 1 楼 yuelengdihai 的回复:]

struct  Data
{
    int  ai;
    int   bi;
}dataB[20];//结构体数组

@yuelengdihai 可是那然后呢?这题的递推公式怎么解[/quote]

int data[20];
for(int i=0;i<n;i++)
{
     data[i]=dataB[i].ai+dataB[i].bi;//data[i]为ai、bi之和
}

如果有需要就根据ai、bi值进行排序
data[]数组中最大值取出来输出就可以了
[/quote]m没有看懂精华呀,烦请再解释一下
童话的守望者 2016-03-09
  • 打赏
  • 举报
回复
引用 1 楼 yuelengdihai 的回复:

struct  Data
{
    int  ai;
    int   bi;
}dataB[20];//结构体数组

@yuelengdihai 可是那然后呢?这题的递推公式怎么解
cocoabird 2016-03-09
  • 打赏
  • 举报
回复
引用 2 楼 yiduiguwen 的回复:
[quote=引用 1 楼 yuelengdihai 的回复:]

struct  Data
{
    int  ai;
    int   bi;
}dataB[20];//结构体数组

@yuelengdihai 可是那然后呢?这题的递推公式怎么解[/quote]

int data[20];
for(int i=0;i<n;i++)
{
     data[i]=dataB[i].ai+dataB[i].bi;//data[i]为ai、bi之和
}

如果有需要就根据ai、bi值进行排序
data[]数组中最大值取出来输出就可以了
cocoabird 2016-03-08
  • 打赏
  • 举报
回复

struct  Data
{
    int  ai;
    int   bi;
}dataB[20];//结构体数组

蓝桥杯简介比赛流程蓝桥杯比赛全程4小时,往年是上午9点到13点。 试题形式题目分为结果填空题和程序设计大题,共10题,大致各占50%,填空题只需要填最后答案,程序设计要求提交完整程序,比赛过程中提交不判断对错,比赛结束后才判题,所以以最后一次提交为准。 对于结果填空题,题目保证只有唯一,选手的结果只有和完全相同才得分。 对于编程大题,会使用多组评测数据来评判,每组评测数据有对应的分数,按照通过的评测数据评分。 比赛准备准备的话(以C++为例),首先是学习编程语言基本语法。 运算,包括逻辑运算和算术运算。 条件表达式,if, else条件判断。 数组,诸如数组定义的合适长度,边界细节,下标是从0开始还是从1开始等。 字符串,掌握字符串的删除,拼接,字符查找等,Java,C/C++,Python都封装了很多字符串的基本操作,学会使用即可。 循环,学会循环的开始和终结的判断,一般使用比较多的就是 for 和 while 。 函数,明白函数的返回类型和参数传递其次,学习基础算法,数据结构和数学知识,排序,这个在比赛中直接使用 sort() 就可以了,还要掌握结构体排序。

64,671

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧