• 刷题记录(NC16645 [NOIP2007]矩阵取数游戏,NC207781 迁徙过程中的河流,NC235953 最大m个子段和)


    NC16645 [NOIP2007]矩阵取数游戏

    题目链接

    关键点:

    1、答案会大于2的80次方,要采用特殊的输入和输出,以及快速幂的运算

    2、从取数规则可以看出,每次取一行,计算每行的得分后算总和,那么说明各行间的取数互不相干,那么我们就可以计算每行取数的最大值,然后相加

    3、对于每行的计算,取方程dp[i][j],为该行取i-j区间内的数,所能得到的最大值,因为每次只能从首尾来取数,

    因此dp[i][j] = max(dp[i+1][j]+t[当前行][i]*(2, n次方), dp[i][j-1]+t[当前行][j]*(2, n次方));

    对于这个n,因为我们求一行的最大值,是从小区间到大区间,而对于大区间的范围,无疑是第一次取的时候,区间越小,当前已经取的次数就越多,所以n = m(总列数)-len(当前区间范围)+1,是先算的最后一次取的数。

    4、答案就为每行求出的dp首位区间的最大值相加,注意点:当更新当前行时,dp要重新赋值为0

    完整代码:

    1. # include
    2. using namespace std;
    3. typedef __int128 ll;
    4. int n, m;
    5. ll ju[100][100];
    6. ll ans = 0;
    7. ll dp[100][100];
    8. ll read()
    9. {
    10. ll s=0, w=1;
    11. char ch = getchar();
    12. while (ch<'0' || ch>'9')
    13. {
    14. if (ch=='-')
    15. w=-w;
    16. ch = getchar();
    17. }
    18. while (ch>='0'&&ch<='9')
    19. {
    20. s = s*10+ch-'0';
    21. ch = getchar();
    22. }
    23. return s*w;
    24. }
    25. void print(ll x)
    26. {
    27. if (x<0)
    28. {
    29. putchar('-');
    30. x = -x;
    31. }
    32. if (x/10)
    33. print(x/10);
    34. putchar(x%10+'0');
    35. }
    36. ll quick(ll x, ll a)
    37. {
    38. ll ans = 1;
    39. while (a)
    40. {
    41. if (a&1)
    42. ans*=x;
    43. x*=x;
    44. a>>=1;
    45. }
    46. return ans;
    47. }
    48. int main()
    49. {
    50. cin>>n>>m;
    51. for (int i=1; i<=n; i++)
    52. {
    53. for (int j=1; j<=m; j++)
    54. ju[i][j] = read();
    55. }
    56. for (int t=1; t<=n; t++)
    57. {
    58. memset(dp, 0, sizeof(dp));
    59. for (int len=1; len<=m; len++)
    60. {
    61. for (int i=1; i+len-1<=m; i++)
    62. {
    63. int j = i+len-1;
    64. dp[i][j] = max(dp[i+1][j]+ju[t][i]*quick(2, m-len+1), dp[i][j-1]+ju[t][j]*quick(2, m-len+1));
    65. }
    66. }
    67. ans += dp[1][m];
    68. }
    69. print(ans);
    70. return 0;
    71. }

    NC207781 迁徙过程中的河流

    题目链接

    关键点:

    1、通过观察可以发现,当人数大于等于三人时,我们需要有人将船给开回来,那么要使时间花费最少,我们就派划船时间最少的来担任划船的角色

    2、对于还剩一个人,和剩两个人的情况是不同的。还剩一个人时,我们只要派花费时间最少的来划船接剩下的人,而剩下两个人时,我们可以从案例中发现,可以先让最少的回来,然后让剩下的两个人划回去,再让花费第二少的回来接花费最少的回去

    3、设dp[i],表示接前i个人所花费的最少时间,设花费最少的时间为t[1], 第二少的为t[2],a[i]为第i个划船时间

    dp[i] = min(dp[i-1]+t[1]+a[i], dp[i-2]+t[1]+a[i]+t[2]+t[2]);

    最终答案即为dp[n(总人数);

    完整代码:

    1. # include
    2. using namespace std;
    3. int n;
    4. int t[100000+10];
    5. int dp[100000+10];//表示前i个过河的最少花费
    6. int main()
    7. {
    8. cin>>n;
    9. for (int i=1; i<=n; i++)
    10. cin>>t[i];
    11. sort(t+1, t+1+n);
    12. dp[1] = t[1];
    13. dp[2] = t[2];
    14. for (int i=3; i<=n; i++)
    15. {
    16. dp[i] = min(dp[i-1]+t[1]+t[i], dp[i-2]+t[1]+t[i]+t[2]+t[2]);
    17. }
    18. cout<
    19. return 0;
    20. }

    NC235953 最大m个子段和

    题目链接

    关键点:

    1、每次选则当前第i个数,要么将其最为上一个字段的一部分,要么作为一个新的字段

    2、对于最为上一个字段的一部分很好解决,那么如何取得最为一个新的字段的最大值呢,那么我们就要算出上一个字段的最大值然后加上当前数即可

    3、dp[i]表示取前i个数所能得到的最大值,maxx[i],表示第i个字段取前i个数的最大和,那么

    dp[i] = max(dp[i-1]+a[i], last[i-1]+a[i]);

    4、题目中给出,每个字段的长度至少为一,所以i每次循环要从当前字段的个数开始

    5、对于last数组的计算,每次在计算出dp[i]时,我们更新一次last数组,加上当前的dp来更新

    6、对于答案,我们遍历一遍dp数组,取最大值,因为对于给出的数字,不一定每一个都要选上

    完整代码:

    1. # include
    2. using namespace std;
    3. typedef long long ll;
    4. int n, m;
    5. ll ans;
    6. const int N = 1000000+10;
    7. ll a[N];
    8. ll maxx[N];
    9. ll dp[N];//表示前i个数组成j个不相交的字串,所得的最大值
    10. int main()
    11. {
    12. cin>>n>>m;
    13. for (int i=1; i<=n; i++)
    14. {
    15. cin>>a[i];
    16. }
    17. memset(dp, -0x3f, sizeof(dp));
    18. for (int i=1; i<=m; i++)
    19. {
    20. for (int j=i; j<=n; j++)
    21. {
    22. dp[j] = max(dp[j-1]+a[j], maxx[j-1]+a[j]);
    23. }
    24. for (int j=i; j<=n; j++)
    25. maxx[j] = max(maxx[j-1], dp[j]);
    26. }
    27. for (int i=1; i<=n; i++)
    28. ans = max(ans, dp[i]);
    29. cout<
    30. return 0;
    31. }

  • 相关阅读:
    Redisson-MultiLock使用
    机器学习---CNN(创建和训练一个卷积神经网络并评估其性能)下
    前后端分离的后台管理系统源码,快速开发OA、CMS网站后台管理、毕业设计项目
    软考45-上午题-【数据库】-数据操纵语言DML
    如何完成企业数据可视化?要从五个方面展开
    【Netty 从成神到升仙系列 三】Netty 凭什么成为国内最流行的网络通信框架?
    Windows使用ssh远程连接(虚拟机)Linux(Ubuntu)的方法
    第6 章 多线程程序设计答案
    Transformers实战——Trainer和文本分类
    Java项目中将MySQL改为8.0以上
  • 原文地址:https://blog.csdn.net/m0_60531106/article/details/126800168