• Preview(2021-2022年度第三届全国大学生算法设计与编程挑战赛(夏季赛)——正式赛——E)


    Preview

    Description

    题目背景

    等上了大学,一切就好起来了。xxx同学一直被家里人这么说,但是实际上,等他上了大学才发现,大学真的太卷了。高中是大家基本都为了高考而努力,但是大学出路有很多条,而且条条路都有很多人在卷,卷的天昏地暗。大学老师经典的一句话是,大学的考试周之前,像是泡脚,轻松而惬意,大学考试周的时候,就是把自己的泡脚水喝下去。而现在,xxx同学正在因为这个考试周忙的头皮发麻,毕竟,他也不想挂科。

    题目描述

    xxx同学一共要学习n节课,我们把n节课要预习准备的时间以ai来进行统计,对于每一节课,我们都知道,学分越高,在大学就代表着学时越长,然后就更加重要,但是,相同学分的学科不一定价值一样,所以我们定义一个bi,代表预习时间的性价比。假设第i门考试会在第i天到来,而xxx同学如果选择在第i天预习这门学科,那么他在(i-ai,i+ai)的时间段就不能预习其他学科,得到的价值为ai*bi,(为什么不是考完就结束预习?因为苦逼的ddl人逃不过各种考完以后相对应的学科要交的报告)。xxx同学已经忙着考试周抽不出身了,他想请你求求能获得的最大价值。

    Input

    一个整数n,代表有n门学科需要预习1 <= n <= 100000

    第二行,连续n个整数,表示要预习的时间ai, 1 <= ai <= n

    第三行,连续n个整数,表示性价比bi,1 <= bi <= 100000

    Output

    一个整数x表示最大的价值

    Sample Input 1

    5
    1 3 2 3 5
    2 2 2 5 2

    Sample Output 1

    17

    1)二维数组设计动态规划:
        状态设计:dp[i][j](i>=j)表示复习后i门课程,从第j天开始的总价值;
            选择第i门课程:  dp[i][j]=dp[i+1][i+a[i]+1]+a[i]*b[i];
            不选择第i门课程:dp[i][j]=dp[i+1][j];
        状态方程:dp[i][j]=max(dp[i+1][j],dp[i+1][i+a[i]+1]+a[i]*b[i]) (i>=j);
        并且由于题目的设定,只能从后往前递推,因为选择了第i门课,那么第i天以后的a[i]天都不能
        复习其他科目;如果从前往前递推,那么我选择了第i门课,那么选择第j门课的时候,要多少天
        以后我们才能选择第j门课呢。因为此时的下标是j,而不是i,无法得到a[i]的数值。

        当然,进行二维设计的时候,空间复杂度O(n^2),显然会爆空间,后面进行一维状态设计求解。

    for(int i=n;i>=1;--i)
            for(int j=i+a[i];j>=i-a[i]&&j>=1;--j)
            {
                if(j>i)
                    dp[i][j]=dp[i+1][j];
                else
                    dp[i][j]=max(dp[i+1][j],dp[i+1][i+a[i]+1]+a[i]*b[i]);
            }

    1. /**
    2. 1)二维数组设计动态规划:
    3. 状态设计:dp[i][j](i>=j)表示复习后i门课程,从第j天开始的总价值;
    4. 选择第i门课程: dp[i][j]=dp[i+1][i+a[i]+1]+a[i]*b[i];
    5. 不选择第i门课程:dp[i][j]=dp[i+1][j];
    6. 状态方程:dp[i][j]=max(dp[i+1][j],dp[i+1][i+a[i]+1]+a[i]*b[i]) (i>=j);
    7. 并且由于题目的设定,只能从后往前递推,因为选择了第i门课,那么第i天以后的a[i]天都不能
    8. 复习其他科目;如果从前往前递推,那么我选择了第i门课,那么选择第j门课的时候,要多少天
    9. 以后我们才能选择第j门课呢。因为此时的下标是j,而不是i,无法得到a[i]的数值。
    10. 当然,进行二维设计的时候,空间复杂度O(n^2),显然会爆空间,后面进行一维状态设计求解。
    11. */
    12. /**
    13. #include
    14. #include
    15. using namespace std;
    16. const int maxn=1e3+10;
    17. int dp[maxn][maxn]={0};
    18. int a[maxn],b[maxn];
    19. int main()
    20. {
    21. int n;
    22. scanf("%d",&n);
    23. for(int i=1;i<=n;++i)
    24. scanf("%d",&a[i]);
    25. for(int i=1;i<=n;++i)
    26. scanf("%d",&b[i]);
    27. for(int i=n;i>=1;--i)
    28. for(int j=i+a[i];j>=i-a[i]&&j>=1;--j)
    29. {
    30. if(i
    31. dp[i][j]=dp[i+1][j];
    32. else
    33. dp[i][j]=max(dp[i+1][j],dp[i+1][i+a[i]+1]+a[i]*b[i]);
    34. }
    35. for(int i=1;i<=n;++i)
    36. {
    37. for(int j=1;j<=n;++j)
    38. cout << dp[i][j] << ' ';
    39. cout << endl;
    40. }
    41. cout << dp[1][1] << endl;
    42. return 0;
    43. }
    44. */

    2)一维数组设计动态归划:去掉二维的第一维便可。

    正确代码

     for(int i=n;i>=1;--i)   //正确代码
            for(int j=i-a[i];j<=i+a[i];++j)
            {
                if(j<0)
                    continue;
                dp[j]=dp[j];
                if(j<=i)
                    dp[j]=max(dp[j],dp[i+a[i]+1]+a[i]*b[i]);
                    //dp[i][j]=max(dp[i+1][j],dp[i+1][[i+a[i]+1]+a[i]*b[i];
            }

      有点错误:

     

    //    for(int i=n;i>=1;--i) //这个应该是有缺陷的
    //        for(int j=i+a[i];j>=i-a[i]&&j>=1;--j)
    //        {
    //            dp[j]=dp[j];
    //            if(j<=i)
    //                dp[j]=max(dp[j],dp[i+a[i]+1]+a[i]*b[i]);
    //                //dp[i][j]=max(dp[i+1][j],dp[i][[i+a[i]+1]+a[i]*b[i];
    //        }

    1. /**
    2. 2)一维数组设计动态归划:
    3. 状态设计:dp[i][j](i>=j)表示复习后i门课程,从第j天开始的总价值;
    4. 选择第i门课程: dp[i][j]=dp[i+1][j+a[i]+1]+a[i]*b[i];
    5. 不选择第i门课程:dp[i][j]=dp[i+1][j];
    6. 状态方程:dp[i][j]=max(dp[i+1][j],dp[i+1][i+a[i]+1]+a[i]*b[i]) (i>=j);
    7. dp[j]=max(dp[j],dp[i+a[i]+1]]+a[i]*b[i]) (i>=j);
    8. 并且由于题目的设定,只能从后往前递推,因为选择了第i门课,那么第i天以后的a[i]天都不能
    9. 复习其他科目;如果从前往前递推,那么我选择了第i门课,那么选择第j门课的时候,要多少天
    10. 以后我们才能选择第j门课呢。因为此时的下标是j,而不是i,无法得到a[i]的数值。
    11. data :
    12. 10
    13. 3 5 6 9 5 4 3 8 7 6
    14. 15 4 6 5 7 9 8 6 7 8
    15. */
    16. #include
    17. #include
    18. using namespace std;
    19. const int maxn=1e6+10;
    20. int dp[2*maxn]={0};
    21. int a[maxn],b[maxn];
    22. int main()
    23. {
    24. int n;
    25. scanf("%d",&n);
    26. for(int i=1;i<=n;++i)
    27. scanf("%d",&a[i]);
    28. for(int i=1;i<=n;++i)
    29. scanf("%d",&b[i]);
    30. for(int i=n;i>=1;--i) //正确代码
    31. for(int j=i-a[i];j<=i+a[i];++j)
    32. {
    33. if(j<0)
    34. continue;
    35. dp[j]=dp[j];
    36. if(j<=i)
    37. dp[j]=max(dp[j],dp[i+a[i]+1]+a[i]*b[i]);
    38. //dp[i][j]=max(dp[i+1][j],dp[i+1][[i+a[i]+1]+a[i]*b[i];
    39. }
    40. // for(int i=n;i>=1;--i) //这个应该是有缺陷的
    41. // for(int j=i+a[i];j>=i-a[i]&&j>=1;--j)
    42. // {
    43. // dp[j]=dp[j];
    44. // if(j<=i)
    45. // dp[j]=max(dp[j],dp[i+a[i]+1]+a[i]*b[i]);
    46. // //dp[i][j]=max(dp[i+1][j],dp[i][[i+a[i]+1]+a[i]*b[i];
    47. // }
    48. // for(int i=1;i<=n;++i)
    49. // cout << dp[i] << ' ';
    50. // cout << endl;
    51. cout << dp[1] << endl;
    52. return 0;
    53. }

  • 相关阅读:
    ABA问题是什么?以及相关解决办法。
    趣味问题《寻人启事》的Python程序解决
    Pytest系列-使用自定义标记mark(6)
    量子计算:数据安全难题
    HTML5期末大作业:HTM+CSS+JS仿安徽开放大学官网(web前端网页制作课作业)
    泰森多边形
    一种实现Spring动态数据源切换的方法
    Himall商城字符串帮助类获得指定顺序的字符在字符串中的位置索引
    查找算法——顺序查找
    Eclipse IDEA VSCode HBuilderX 统一快捷键
  • 原文地址:https://blog.csdn.net/qq_51825761/article/details/126002574