• DP(动态规划)【2】 最大连续子列和 最长不降子序列


    1.最大连续子列和

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. const int N=10002,maxn=10;int n,m,k,f[N]={0},dp[N]={0};
    9. int main()
    10. {scanf("%d",&n);
    11. for(int i=0;iscanf("%d",&f[i]);
    12. //一定要以i结尾!!
    13. dp[0]=f[0];
    14. int ans=f[0];
    15. for(int i=1;i
    16. {
    17. dp[i]=max(f[i],dp[i-1]+f[i]);
    18. if(dp[i]>ans) ans=dp[i];
    19. }
    20. // for(int i=1;i
    21. printf("%d",ans);
    22. }

     输出最大方案

    这样写是不对的,只在dp[i]>ans才更新ans_i,举个例子

    1,-2,0.5,1

    导致ans_i=0

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. const int N=10002,maxn=10;int n,m,k,f[N]={0},dp[N]={0};
    9. int main()
    10. {scanf("%d",&n);
    11. for(int i=0;iscanf("%d",&f[i]);
    12. //一定要以i结尾!!
    13. dp[0]=f[0];
    14. int ans=f[0];
    15. int ans_i=0;
    16. int ans_j=0;
    17. for(int i=1;i
    18. {
    19. dp[i]=max(f[i],dp[i-1]+f[i]);
    20. if(dp[i]>ans)
    21. {
    22. ans=dp[i];ans_j=i;
    23. if(dp[i-1]<0) ans_i=i;
    24. }
    25. }
    26. // for(int i=1;i
    27. printf("%d %d %d",ans,ans_i+1,ans_j+1);
    28. }

    由于少了一句话一直在错,加上就对了

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. const int N=10002,maxn=10;int n,m,k,f[N]={0},dp[N]={0};
    9. int main()
    10. {scanf("%d",&n);
    11. for(int i=0;iscanf("%d",&f[i]);
    12. //一定要以i结尾!!
    13. dp[0]=f[0];
    14. int ans=f[0];
    15. int ans_i=0;
    16. int ans_j=0;
    17. int ans_i2=0;
    18. for(int i=1;i
    19. {
    20. if(dp[i-1]<0)
    21. {ans_i=i;dp[i]=f[i];
    22. if(dp[i]>ans)
    23. {ans=dp[i];ans_i2=ans_i;ans_j=i;
    24. }
    25. }
    26. else
    27. {dp[i]=f[i]+dp[i-1];
    28. if(dp[i]>ans)
    29. {ans=dp[i];ans_j=i;
    30. ans_i2=ans_i;//就缺这句话!
    31. }
    32. }
    33. }
    34. // dp[i]=max(f[i],dp[i-1]+f[i]);
    35. // if(dp[i]>ans)
    36. // {
    37. // ans=dp[i];ans_j=i;
    38. // if(dp[i-1]<0) ans_i=i;
    39. // }
    40. // }
    41. // for(int i=1;i
    42. printf("%d %d %d",ans,ans_i2+1,ans_j+1);
    43. }

    答案

    用了一个数组存储以i为结尾的start

    1. #include
    2. #include
    3. using namespace std;
    4. const int MAXN = 10000;
    5. int a[MAXN];
    6. int dp[MAXN], start[MAXN];
    7. int main() {
    8. int n;
    9. scanf("%d", &n);
    10. for (int i = 0; i < n; i++) {
    11. scanf("%d", &a[i]);
    12. }
    13. dp[0] = a[0];
    14. start[0] = 0;
    15. for (int i = 1; i < n; i++) {
    16. if (dp[i - 1] >= 0) {
    17. dp[i] = dp[i - 1] + a[i];
    18. start[i] = start[i - 1];
    19. } else {
    20. dp[i] = a[i];
    21. start[i] = i;
    22. }
    23. }
    24. int k = 0;
    25. for (int i = 1; i < n; i++) {
    26. if (dp[i] > dp[k]) {
    27. k = i;
    28. }
    29. }
    30. printf("%d %d %d", dp[k], start[k] + 1, k + 1);
    31. return 0;
    32. }

    难点:如何设计状态状态转移方程

    本题

    状态 取:以第i位结尾的连续子序列最大和

    2.最长不降子序列

    如果要用枚举,复杂度2^n

    状态:以第i个数结尾的序列长度dp[i]

    状态转移方程

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. const int N=10002,maxn=10;int n,m,k,f[N]={0},dp[N]={0};
    9. int main()
    10. {scanf("%d",&n);
    11. for(int i=0;iscanf("%d",&f[i]);
    12. //一定要以i结尾!!
    13. dp[0]=1;
    14. int temp=1;
    15. int ans=1;
    16. for(int i=1;i
    17. {temp=1;
    18. for(int j=0;j
    19. {if(f[i]>=f[j])
    20. {
    21. if(dp[j]+1>temp){temp=dp[j]+1;//dp[i]=temp;
    22. }
    23. }
    24. }
    25. dp[i]=temp;
    26. if(ans
    27. }
    28. // for(int i=1;i
    29. printf("%d",ans);
    30. }

    写完发现,temp其实是多余的)

    输出最大方案

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. const int N=10002,maxn=10;int n,m,k,f[N]={0},dp[N]={0};
    9. int main()
    10. {scanf("%d",&n);
    11. for(int i=0;iscanf("%d",&f[i]);
    12. //一定要以i结尾!!
    13. dp[0]=1;
    14. int temp=1;
    15. int ans=1;
    16. //int l=0,r=0;
    17. int anslist[n]={0};
    18. int lst=0;
    19. for(int i=1;i
    20. {temp=1;
    21. for(int j=0;j
    22. {if(f[i]>=f[j])
    23. {
    24. if(dp[j]+1>temp){temp=dp[j]+1;anslist[i]=j;
    25. }
    26. }
    27. }
    28. dp[i]=temp;
    29. if(ans
    30. { ans=temp;lst=i;//寻址
    31. }
    32. }
    33. // for(int i=1;i
    34. //printf("%d",dp[i]);
    35. printf("%d\n",ans);
    36. int p[n];int k=0,t=lst;
    37. p[0]=f[lst];
    38. while(t>0)
    39. {//k++;
    40. if(anslist[t]==0)
    41. {if(p[k]>=f[0])
    42. {k++;t=anslist[t];p[k]=f[t];
    43. }
    44. else t=0;
    45. }
    46. else
    47. {k++;
    48. t=anslist[t];
    49. p[k]=f[t];
    50. }
    51. }
    52. for(int i=k;i>=0;i--)
    53. {printf("%d",p[i]); if(i>0) printf(" ");
    54. }
    55. }

  • 相关阅读:
    MySQL高级-读写分离-分库分表
    边缘云服务提供商[网心科技],入选2022信通院“可信边缘计算推进计划”首批成员单位
    2024年高考:计算机相关专业前景分析与选择建议
    debug设置
    985硕的4家大厂实习与校招经历专题分享(part2)
    尚品汇后台管理项目SPU模块和SKU模块的实现
    python模块之aioFile 异步读取文件
    Dubbo3的Triple协议踩坑记录
    检测Windows电脑网络是否在线、离线方法(c++)-->ConnectivityChanged
    【离散数学】谓词逻辑
  • 原文地址:https://blog.csdn.net/m0_68339197/article/details/140051935