最大子列和问题 (20 分)

本文深入探讨了三种经典算法——简单搜索、动态规划及分治法,在解决特定问题时的具体实现与应用。通过对比分析,展示了每种算法的优缺点及其适用场景,为读者提供了丰富的代码实例与调试经验分享。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题目链接

  • 算法2:
    拿起脑子想的就是这个,so easy,除了注释一次通过(注释只有自己能懂系列)
#include <stdio.h>
#include <stdlib.h>//??? stblib.h
#define Maxsize 100000//MAXSIZE

int simplesearch(int p[],int b);

int main()
{
    int b,i,j,maxadd;
    //scanf("%d",&b);
    int a[Maxsize];
    scanf("%d",&b);
    for(i=0;i<b;i++)
    scanf("%d",&a[i]);
    maxadd=simplesearch(a,b);
    printf("%d",maxadd);
    return 0;
}

int simplesearch(int p[],int b){
    int maxadd=0;
    int i,j,max;
    for (i=0;i<b;i++){
        max=0;
        for(j=i;j<b;j++){
            max+=p[j];
            if(max>maxadd)
            maxadd=max;
        }
    }
    return maxadd;
}
  • 算法4:在线搜索,是一种动态规划
    惭愧惭愧,又回头看视频才知道怎么写
#include <stdio.h>
#include <stdlib.h>//??? stblib.h
#define Maxsize 100000//MAXSIZE

int onlinesearch(int p[],int b);

int main()
{
    int b,i,j,maxadd;
    //scanf("%d",&b);
    int a[Maxsize];
    scanf("%d",&b);
    for(i=0;i<b;i++)
    scanf("%d",&a[i]);
    maxadd=onlinesearch(a,b);
    printf("%d",maxadd);
    return 0;
}

int onlinesearch(int p[],int b){
    int max=0;
    int i;
    int thissum=0;
    for(i=0;i<b;i++){
        thissum+=p[i];
        if(thissum>max)
            max=thissum;
        else if (thissum<0)//忘记了,看不懂就找MOOC 
            thissum=0;
    }
    return max;
}
  • 算法3:分治,算是递归的进阶吧

    附上分治法试用条件

    1. 该问题的规模缩小到一定的程度就可以容易地解决;
      因为问题的计算复杂性一般是随着问题规模的增加 而增加,因此大部分问题满足这个特征。
    2. 该问题可以分解为若干个规模较小的相同问题,即该问 题具有最优子结构性质
      这条特征是应用分治法的前提,它也是大多数问题可 以满足的,此特征反映了递归思想的应用。
    3. 利用该问题分解出的子问题的解可以合并为该问题的解;
      能否利用分治法完全取决于问题是否具有这条特征,如果具 备了前两条特征,而不具备第三条特征,则可以考虑贪心算 法或动态规划。
    4. 该问题所分解出的各个子问题是相互独立的,即子问题之间 不包含公共的子问题。
      这条特征涉及到分治法的效率,如果各子问题是不独立的,则分治法 要做许多不必要的工作,重复地解公共的子问题(也就是本算法中求跨分界线的最大子列和 ),此时虽然也可用分 治法,但一般用动态规划较好(也就是算法4!!!)。
分治法的基本步骤
divide-and-conquer(P) 
{
    if ( | P | <= n0) adhoc(P);   //解决小规模的问题 
    divide P into smaller subinstances P1,P2,...,Pk;//分解问题 
    for (i=1,i<=k,i++) 
    yi=divide-and-conquer(Pi);  //递归的解各子问题 
    return merge(y1,...,yk);  //将各子问题的解合并为原问题的解 
}

之前两个算法用dev不用调试,这个是visual stdio,方便调试,所以代码有点儿不同之处,纪念我第一次用vs写代码,并且调试后找出错误了


#include <stdio.h>
#include <stdlib.h>//??? NOTstblib.h
#define Maxsize 100000//MAXSIZE

int divideandconquer(int p[], int left, int right);
int max3(int a, int b, int c);

int main()
{
    int b, i, maxadd;
    //scanf("%d",&b);
    int a[Maxsize];
    scanf_s("%d", &b);
    for (i = 0; i<b; i++)
        scanf_s("%d", &a[i]);
    maxadd = divideandconquer(a, 0, b - 1);     //b-1
    printf("%d", maxadd);
    system("pause");    //为了不让结果准瞬即逝
    return 0;
}

int divideandconquer(int p[], int left, int right) {

    int mid, i;
    int leftmax, rightmax;
    int leftadd, rightadd;
    int leftaddmax, rightaddmax;
    leftaddmax = leftadd = 0;   //放这试试 
    rightadd = rightaddmax = 0; //两遍不一样!!!
    int max = 0;
    /*if(b<2){
    left=p[mid];
    right=p[mid+1];
    max=left>right?left:right;
    */
    if (left == right) {    //终止条件只有一个数字 
        if (p[left]>0)  return p[left]; //不是[i] 
        else    return 0;
    }
    mid = (left + right) / 2;
    leftmax = divideandconquer(p, left, mid);       //赋值给 
    rightmax = divideandconquer(p, mid + 1, right); //mid+1


    for (i = mid; i >= left; i--){  //NOT i>=0  i有问题(for循环后多加了;)
        leftadd += p[i];    //NOT p[mid]
        if (leftadd>leftaddmax)
            leftaddmax = leftadd;
    }

    for (i = mid + 1; i <= right; i++) {    //NOT i>=0
        rightadd += p[i];   //NOT p[mid]
        if (rightadd>rightaddmax)
            rightaddmax = rightadd;
    }

    return max3(leftmax, rightmax, leftaddmax + rightaddmax);
}

int max3(int a, int b, int c) {
    return a>b ? (a>c ? a : c) : (b>c ? b : c);     //输出大的就和大的比较,括号可省略 
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值