• 刷题记录(NC50959 To the Max,NC236172 货船,NC16655 [NOIP2005]过河)


    NC50959 To the Max

    题目链接

    关键点:

    1、题目要求求出二维数组里矩形的最大值,首先我们可以想到的是枚举矩形的左上角、右上角的端点,用二维数组前缀和可以减少计算。

    对于前缀和sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];

    然后对于左上角(i, j),右下角(k1, k2),该区间的和为

    ans = max(ans, sum[k1][k2]-sum[i-1][k2]-sum[k1][j-1]+sum[i-1][j-1]);

    完整代码:

    1. # include
    2. using namespace std;
    3. int n;
    4. int g[110][110];
    5. int sum[110][110];
    6. int res = -300, last, ans;
    7. int main()
    8. {
    9. cin>>n;
    10. for (int i=1; i<=n; i++)
    11. {
    12. for (int j=1; j<=n; j++)
    13. {
    14. cin>>g[i][j];
    15. // g[i][j] += g[i-1][j];
    16. }
    17. }
    18. for (int i=1; i<=n; i++)
    19. {
    20. for (int j=1; j<=n; j++)
    21. {
    22. sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+g[i][j];
    23. }
    24. }
    25. for (int i=1; i<=n; i++)
    26. {
    27. for (int j=1; j<=n; j++)
    28. {
    29. for (int k1=i; k1<=n; k1++)
    30. {
    31. for (int k2=j; k2<=n; k2++)
    32. {
    33. ans = max(ans, sum[k1][k2]-sum[i-1][k2]-sum[k1][j-1]+sum[i-1][j-1]);
    34. }
    35. }
    36. }
    37. }
    38. cout<
    39. // cout<
    40. return 0;
    41. }

    2、如果N很大,那么该方法就会超时,我们可以减少一层for循环,通过枚举选择的两行,在选出的两行中求该区间内连续的最大值,每次更新这个答案

    3、首先我们要先算出每行的前缀和,当在选择的两行中遍历列时,对于之前的列是否要选上,我们可以每次用一个值记住上一次计算出来的先前列(选出的两行中)的最大值,如果是大于零的,那么我们是可以加上先前列的值。记住每次都要更新答案

    完整代码:

    1. # include
    2. using namespace std;
    3. int n;
    4. int g[110][110];
    5. int res = -300, last;
    6. int main()
    7. {
    8. cin>>n;
    9. for (int i=1; i<=n; i++)
    10. {
    11. for (int j=1; j<=n; j++)
    12. {
    13. cin>>g[i][j];
    14. g[i][j] += g[i-1][j];
    15. }
    16. }
    17. for (int i=1; i<=n; i++)
    18. {
    19. for (int j=i; j<=n; j++)
    20. {
    21. last = 0;
    22. for (int k=1; k<=n; k++)
    23. {
    24. last = max(last, 0) + g[j][k]-g[i-1][k];
    25. res = max(res, last);
    26. }
    27. }
    28. }
    29. cout<
    30. return 0;
    31. }

    NC236172 货船

    题目链接

    关键点:

    1、该题第一眼看的想法是,用数组dp[i],表示载重量为i时的最大的装载重量,然后用两层循环,从数据可以看出,肯定会超时

    2、想法没有问题,我们可以想办法减少循环,用bitset数组b,对于可以组成的装载量的位置上置为1,首先我们初始化将第0为置为1,因为装载量为0千克,是可以实现的。

    3、之后循环一遍货物,每次在该b数组上将可以组成的装载量的位置置为1,我们可以采用或运算,对于已经组成的装载量,他就会一直存在,且会影响后序装载量

    b = b|(b<<w[i]);

    4、最后我们从题目给出的最大装载量开始从大到小遍历b数组,有位置为1,那么该下标即为最大的装载量

    完整代码:

    1. # include
    2. using namespace std;
    3. int n, a;
    4. int w[100000+10];
    5. int dp[100000+10];
    6. bitset<100000+10>b;//表示第i千克是否能取到
    7. int main()
    8. {
    9. cin>>n>>a;
    10. for (int i=1; i<=n; i++)
    11. cin>>w[i];
    12. b.set(0, 1);
    13. for (int i=1; i<=n; i++)
    14. b = b|(b<
    15. for (int i=a; i>=0; i--)
    16. {
    17. if (b[i])
    18. {
    19. cout<
    20. break;
    21. }
    22. }
    23. return 0;
    24. }

    NC16655 [NOIP2005]过河

    题目链接

    关键点:

    1、首先设dp[i],表示到达i距离,所跳的最少石头数,vis表示该点是否有石头(有为1,无为0)

    dp[i] = min(dp[i-s]+vis[i], dp[i-s+1]+vis[i].....),很明显我们需要有两层循环,一层是遍历从起点到桥的距离,一层是遍历跳跃距离,很明显会超时

    2、可以发现对于最后一个石头之后的位置对答案不产生影响,然后对于每个石头之间的距离,当石头之间的距离超过一定值时,我们是可以将其忽略,因为在这距离之后很有可能是重复之前的跳跃的方式,那么该值我们就取1-10的最小公倍数2050,在2050距离之后所有的距离都为先前跳跃的重复,我们可以将该距离对2050取余,这样一来就大大减少了最后一个石头的距离,不会超过10^6;

    3、然后我们就可以开始用该距离开始遍历,最后的答案就从这个最后一个石头的距离到该距离+最长步数里面再取最小值

    4、这里还有一特判,对于最小步数和最长步数相同的情况,我们可以直接看石头为该步数的倍数的数量,即为答案

    完整代码:

    1. # include
    2. using namespace std;
    3. int l, s, t, m;
    4. int vis[10000000];
    5. int dp[10000000];
    6. int a[100+10];
    7. int dis[110];
    8. int ans;
    9. int main()
    10. {
    11. cin>>l>>s>>t>>m;
    12. for (int i=1; i<=m; i++)
    13. cin>>a[i];
    14. sort(a+1, a+1+m);
    15. if (s==t)
    16. {
    17. for (int i=1; i<=m; i++)
    18. {
    19. if (a[i]%t == 0)
    20. ans++;
    21. }
    22. cout<
    23. return 0;
    24. }
    25. for (int i=1; i<=m; i++)
    26. {
    27. dis[i] = (a[i]-a[i-1])%2050;
    28. }
    29. int len = 0;
    30. for (int i=1; i<=m; i++)
    31. {
    32. len += dis[i];
    33. vis[len] = 1;
    34. }
    35. memset(dp, 0x3f, sizeof(dp));
    36. dp[0] = 0;
    37. for (int i=1; i<=len+t; i++)
    38. {
    39. for (int j=s; j<=t; j++)
    40. {
    41. if (i-j>=0)
    42. dp[i] = min(dp[i-j]+vis[i], dp[i]);
    43. }
    44. }
    45. ans = 110;
    46. for (int i=len; i<=len+t; i++)
    47. ans = min(ans, dp[i]);
    48. cout<
    49. return 0;
    50. }

  • 相关阅读:
    qt creator5.15.2用的是什么版本的图形api?
    遥感和GIS在滑坡、泥石流风险普查中的应用
    java.lang.Float类下toString(float f)方法具有什么功能呢?
    OA项目之会议发布
    记录Oracle rac 19C(19.15)补丁升级(OPatch 33803476)操作过程
    [LeetCode]-链表-3
    走出3个新生儿喂养误区,新手爸妈变高手
    Pycharm中右键运行python程序时出现Run ‘pytest in XXX.py
    SfM——八点法计算F矩阵(基础矩阵)与三角测量
    React学习笔记
  • 原文地址:https://blog.csdn.net/m0_60531106/article/details/126810018