• [USACO24JAN] Cannonball B 题解


    目录

    题目传送门

    题意与任务和结果

    75分的代码

    75分代码分析

    修改后程序的模拟部分代码

    AC代码


    题目传送门

    题意与任务和结果

    看完题目后,我们了解到了其实题目就是一个模拟的题目,无疑就是模拟Bessie在数轴上的行动,模拟的答案是Bessie在数轴上击破的炮击目标,只是每个数轴上的整数点上都有一个需要处理的子任务。根据题意,子任务大致有两种:

    •   是这个点上的是一个炮击目标(也就是q=1)
    •   是这个点上的是一个跳板(也就是q=0)

    在细分该子任务的其他子任务,那么每一个点上都有一个结果:

    •  这个点上是炮击目标,且未被炮击过且k(能量)$\ge$v时,炮击目标+1
    •  这个点上是炮击目标,且未被炮击过且k(能量)$\le$v时,炮击目标+0
    •  这个点上是炮击目标,且被炮击过时,炮击目标+0
    •  这个点上是跳板时,跳转方向翻转(如向右变向左),k值发生变化,k=k+v

     
    还需要考虑什么时候结束:

    •  弹跳无限长的时间或直到她离开数轴时结束

    75分的代码

    那么这些我们都列举出来了,模拟这个过程也就轻而易举了。
    模拟代码如下:

    1. #include
    2. using namespace std;
    3. long long n,s,p,q[100005],v[100005],ans,k=1;
    4. bool flag,m[100005];
    5. int main()
    6. {
    7. cin>>n>>s;
    8. p=s;
    9. for(int i=1;i<=n;i++)
    10. {
    11. cin>>q[i]>>v[i];
    12. }
    13. if(q[p]==1)
    14. {
    15. if(k>=v[p]&&m[p]==0)
    16. {
    17. ans++;
    18. m[p]=1;
    19. }
    20. }
    21. else
    22. {
    23. k+=v[p];
    24. flag=1;
    25. }
    26. while(p>=1&&p<=n)
    27. {
    28. if(flag==0)
    29. {
    30. p+=k;
    31. if(q[p]==1)
    32. {
    33. if(k>=v[p]&&m[p]==0)
    34. {
    35. ans++;
    36. m[p]=1;
    37. }
    38. }
    39. else
    40. {
    41. k+=v[p];
    42. if(flag==1)
    43. {
    44. flag=0;
    45. }
    46. else
    47. {
    48. flag=1;
    49. }
    50. }
    51. }
    52. else
    53. {
    54. p-=k;
    55. if(q[p]==1)
    56. {
    57. if(k>=v[p]&&m[p]==0)
    58. {
    59. ans++;
    60. m[p]=1;
    61. }
    62. }
    63. else
    64. {
    65. k+=v[p];
    66. if(flag==1)
    67. {
    68. flag=0;
    69. }
    70. else
    71. {
    72. flag=1;
    73. }
    74. }
    75. }
    76. //cout<
    77. }
    78. cout<
    79. return 0;
    80. }

    75分代码分析

    我们用两个整形数组分别储存v和q,然后再用一个bool的数组储存该炮击目标是否被炮击过,再用一个bool的变量判断向左还是向右(0向右,1向左),那么程序的模拟范围就在[1,n]中,再根据上述我们列出的的子任务和结果进行模拟,那么结果就非常轻松地出来了。

    但......

     上述代码结果如下

    只有75分......

    我们发现T了5个点。

    该怎么办呢?我们不妨猜一下当Bessie在数轴上的两个跳板之间来回跳跃,那是不是就死循环了。题目中有一句话:

    • 如果 Bessie 弹跳无限长的时间或直到她离开数轴,她会击破多少个炮击目标?

    也就是说但Bessie 弹跳无限长的时间或直到她离开数轴时,这个模拟程序就结束。我们好像并没有考虑到要判断是否弹跳无限长时间。所以T了。

    那我们只需要加一个变量t,放在while的开头,每次都+1,如果Bessie跳到了炮击目标上,就将t给清零,因为并没有在反复跳,当t$\ge$n时,也就意味着我已经弹跳了超过n次且没有到过炮击目标,也就是跳跃时间无限长的情况,我们满足这个情况跳出这个模拟程序即可。

    修改后程序的模拟部分代码

    那么模拟程序也就会变成下面这个程序:

    1. while(p>=1&&p<=n)
    2. {
    3. r++;
    4. if(r==n)
    5. {
    6. break;
    7. }
    8. if(flag==0)
    9. {
    10. p+=k;
    11. if(q[p]==1)
    12. {
    13. if(k>=v[p]&&m[p]==0)
    14. {
    15. ans++;
    16. m[p]=1;
    17. r=0;
    18. }
    19. }
    20. else
    21. {
    22. k+=v[p];
    23. if(flag==1)
    24. {
    25. flag=0;
    26. }
    27. else
    28. {
    29. flag=1;
    30. }
    31. }
    32. }
    33. else
    34. {
    35. p-=k;
    36. if(q[p]==1)
    37. {
    38. if(k>=v[p]&&m[p]==0)
    39. {
    40. ans++;
    41. m[p]=1;
    42. r=0;
    43. }
    44. }
    45. else
    46. {
    47. k+=v[p];
    48. if(flag==1)
    49. {
    50. flag=0;
    51. }
    52. else
    53. {
    54. flag=1;
    55. }
    56. }
    57. }
    58. //cout<
    59. }

    这样这个问题就结束了。

    AC代码

    附上AC代码

    1. #include
    2. using namespace std;
    3. long long n,s,p,q[100005],v[100005],ans,k=1,r;
    4. bool flag,m[100005];
    5. int main()
    6. {
    7. cin>>n>>s;
    8. p=s;
    9. for(int i=1;i<=n;i++)
    10. {
    11. cin>>q[i]>>v[i];
    12. }
    13. if(q[p]==1)
    14. {
    15. if(k>=v[p]&&m[p]==0)
    16. {
    17. ans++;
    18. m[p]=1;
    19. }
    20. }
    21. else
    22. {
    23. k+=v[p];
    24. flag=1;
    25. }
    26. while(p>=1&&p<=n)
    27. {
    28. r++;
    29. if(r==n)
    30. {
    31. break;
    32. }
    33. if(flag==0)
    34. {
    35. p+=k;
    36. if(q[p]==1)
    37. {
    38. if(k>=v[p]&&m[p]==0)
    39. {
    40. ans++;
    41. m[p]=1;
    42. r=0;
    43. }
    44. }
    45. else
    46. {
    47. k+=v[p];
    48. if(flag==1)
    49. {
    50. flag=0;
    51. }
    52. else
    53. {
    54. flag=1;
    55. }
    56. }
    57. }
    58. else
    59. {
    60. p-=k;
    61. if(q[p]==1)
    62. {
    63. if(k>=v[p]&&m[p]==0)
    64. {
    65. ans++;
    66. m[p]=1;
    67. r=0;
    68. }
    69. }
    70. else
    71. {
    72. k+=v[p];
    73. if(flag==1)
    74. {
    75. flag=0;
    76. }
    77. else
    78. {
    79. flag=1;
    80. }
    81. }
    82. }
    83. //cout<
    84. }
    85. cout<
    86. return 0;
    87. }

    完结,感谢阅读。

  • 相关阅读:
    《对比Excel,轻松学习Python数据分析》读书笔记------结果导出
    OpenGL入门(四)之纹理Texture
    css魔法--利用css变量打造滚动指示器
    资源分享 | 情绪脑电研究公开数据集
    c++ static
    对时序数据进行分类与聚类
    树莓派通过frp实现内网穿透打通ssh[操作记录]
    基于帧间差分法的视频目标检测研究-含Matlab代码
    A. Common Prefixes
    JAVA8 - java.util.function.Predicate
  • 原文地址:https://blog.csdn.net/lsj0929/article/details/136220428