首页 > 其他 > 详细

[洛谷]kkksc03考前临时抱佛脚

时间:2020-05-07 21:06:24      阅读:80      评论:0      收藏:0      [点我收藏+]

题目背景

kkksc03 的大学生活非常的颓废,平时根本不学习。但是,临近期末考试,他必须要开始抱佛脚,以求不挂科。

题目描述

这次期末考试,kkksc03 需要考 44 科。因此要开始刷习题集,每科都有一个习题集,分别有 s_1,s_2,s_3,s_4s1?,s2?,s3?,s4? 道题目,完成每道题目需要一些时间,可能不等(A_1,A_2,\ldots,A_{s_1}A1?,A2?,,As1??B_1,B_2,\ldots,B_{s_2}B1?,B2?,,Bs2??C_1,C_2,\ldots,C_{s_3}C1?,C2?,,Cs3??D_1,D_2,\ldots,D_{s_4}D1?,D2?,,Ds4??)。

kkksc03 有一个能力,他的左右两个大脑可以同时计算 22 道不同的题目,但是仅限于同一科。因此,kkksc03 必须一科一科的复习。

由于 kkksc03 还急着去处理洛谷的 bug,因此他希望尽快把事情做完,所以他希望知道能够完成复习的最短时间。

输入格式

本题包含 55 行数据:第 11 行,为四个正整数 s_1,s_2,s_3,s_4s1?,s2?,s3?,s4?

第 22 行,为 A_1,A_2,\ldots,A_{s_1}A1?,A2?,,As1?? 共 s_1s1? 个数,表示第一科习题集每道题目所消耗的时间。

第 33 行,为 B_1,B_2,\ldots,B_{s_2}B1?,B2?,,Bs2?? 共 s_2s2? 个数。

第 44 行,为 C_1,C_2,\ldots,C_{s_3}C1?,C2?,,Cs3?? 共 s_3s3? 个数。

第 55 行,为 D_1,D_2,\ldots,D_{s_4}D1?,D2?,,Ds4?? 共 s_4s4? 个数,意思均同上。

输出格式

输出一行,为复习完毕最短时间。

输入输出样例

输入 #1
1 2 1 3		
5
4 3
6
2 4 3
输出 #1
20

 

题解

这道题可以使用搜索来做,也可以使用DP。

个人认为DP的思维难度较高一点:

原因是那个单科总时间的一半,不好理解。

想法:

对于任意学科来说:最好的结果就是一半,左右脑同时协力,也就是说最多的情况下,半脑只能做一半的事。

也就是说,再给了一半的时间下,多余的事不是不想做,而是做不了。你一半只能做这么多了,这是做多了。多余的自然堆给另外一半了

也许会有个疑问?凭什么啊?凭啥右边接替另外一半?就不能左边继续做吗?

换个角度想想,我们分别考虑左右脑。

假设左脑解题时,右脑不动。是不是显然,与其不动不如挂在右脑上面让它思考?

对不对?

所以说右脑做的是左脑一半时间内没有办法完成的工作了。

有人会疑惑?哎我为啥就给左脑一半时间啊,我就不能让它多一点,这样多帮右脑干一点,

但是这个时间是从哪里来的呢?

这一半的时间实际上是从总时间扣的,也就是说俩者是对称的。所以说如果某一个脑袋给的时间多或少了,另外的就会进入闲置状态

因此干事干的最多的就是中间状态。代表了这个半脑在一半时间内能完成的最多题目

有人又要说了?

哎不对啊,你要是 1 9 这个数据怎么办?

一半时间你完成不了  9 啊。

这里总时间是 10 

给 5 到左脑

他只能是完成 1

9则一开始就由右脑快加鞭的完成

所以最后是max(dp[m/2],m-dp[m/2]) = 9 的

 就是因为最后这个max式子

你给任意一边时间多了就象征着另一边少了,它就做事少了。

那有人会问,会不会浪费呢?

假如左脑做不完一半的事情。

事实上不会的,因为算的是你实际做完的,也就是你的工作时间,分配给你的时间不会算在其中

 

技术分享图片

 

 

#include <iostream>
using namespace std;
int a, b, c, d;
int A[25]{0};
int B[25]{0};
int C[25]{0};
int D[25]{0};
int m_a = 0, m_b = 0, m_c = 0, m_d = 0;
int ans = 0; //负责记录总数
void start() //初始化,录入数据
{
    for (int i = 0; i < a; i++)
    {
        cin >> A[i];
        m_a += A[i];
    }
    for (int i = 0; i < b; i++)
    {
        cin >> B[i];
        m_b += B[i];
    }
    for (int i = 0; i < c; i++)
    {
        cin >> C[i];
        m_c += C[i];
    }
    for (int i = 0; i < d; i++)
    {
        cin >> D[i];
        m_d += D[i];
    }
}

void work_a(int n)
{
    int dp[m_a]{0};
    for (int i = 0; i < n; i++) //这是第i道题目
    {
        for (int r = m_a / 2; r >= A[i]; r--)
        {
            dp[r] = max(dp[r], dp[r - A[i]] + A[i]);
        }
    }
    ans += max(dp[m_a / 2], m_a - dp[m_a / 2]);
}
void work_b(int n)
{
    int dp[m_b]{0};
    for (int i = 0; i < n; i++) //这是第i道题目
    {
        for (int r = m_b / 2; r >= B[i]; r--)
        {
            dp[r] = max(dp[r], dp[r - B[i]] + B[i]);
        }
    }
    ans += max(dp[m_b / 2], m_b - dp[m_b / 2]);
}
void work_c(int n)
{
    int dp[m_c]{0};
    for (int i = 0; i < n; i++) //这是第i道题目
    {
        for (int r = m_c / 2; r >= C[i]; r--)
        {
            dp[r] = max(dp[r], dp[r - C[i]] + C[i]);
        }
    }
    ans += max(dp[m_c / 2], m_c - dp[m_c / 2]);
}
void work_d(int n)
{
    int dp[m_d]{0};
    for (int i = 0; i < n; i++) //这是第i道题目
    {
        for (int r = m_d / 2; r >= D[i]; r--)
        {
            dp[r] = max(dp[r], dp[r - D[i]] + D[i]);
        }
    }
    ans += max(dp[m_d / 2], m_d - dp[m_d / 2]);
}
int main()
{
    cin >> a >> b >> c >> d; //四种学科的题目数量
    start();
    work_a(a);
    work_b(b);
    work_c(c);
    work_d(d);
    cout << ans << endl;
    return 0;
}

 

[洛谷]kkksc03考前临时抱佛脚

原文:https://www.cnblogs.com/leader-one/p/12845324.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!