最优子序列问题(减而治之 - 二分查找 - 分组)

Posted ziyang1060

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最优子序列问题(减而治之 - 二分查找 - 分组)相关的知识,希望对你有一定的参考价值。

技术图片

 

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 int isSright(int *arr,int N,int M,int S);//判断S是否可能为数列分组的和
 4 int dichotomy(int *arr,int N,int M);//对S的上下限使用二分法
 5 int main(void)
 6 {
 7     int*arr,N,M,i;//n个数字,m份
 8 
 9     scanf("%d %d",&N,&M);
10     arr=(int*)malloc(sizeof(int)*N);//动态分配内存
11     for(i=0;i<N;i++)
12         scanf("%d",arr+i);
13     printf("%d
",dichotomy(arr,N,M));
14     free(arr);
15     arr=NULL;
16 
17     return 0;
18 }
19 int isSright(int *arr,int N,int M,int S)
20 {
21     int j=0;
22     int currentS=0;//尝试分割过程中,当前分割的部分和
23     int sum=1;// 记录尝试分割过程中已分的份数
24     for(j=0;j<N;j++)
25     {
26         if(*(arr+j)>S) return 0;//如果出现单个元素超过S直接返回0
27         currentS+=arr[j];
28         if(currentS>S)
29         {
30             currentS=0;
31             sum++;
32             j--;
33         }
34     }
35     if(sum>M) return 0;
36     else return 1;
37 }
38 int dichotomy(int *arr,int N,int M)//二分法
39 {
40     int i=0;
41     int left=0,right=0,middle=0;
42     for(i=0;i<N;i++)
43         right+=*(arr+i);
44     while(left<=right)
45     {
46         middle=(left+right)/2;
47         if(isSright(arr,N,M,middle)==1)    right=middle-1;
48         else    left=middle+1;
49     }
50     return left;
51 }

明确两点:第一,该数列是正整数列,S的最大值应为全部数字的和,所以S的上限很容易

        确定。只要我确定当前S的可行性,就能确定下一个S的范围,由此想到

        可以利用二分法来完成。

     第二,对于每个S可行性的检查,在数组中按原顺序一直累加,直至恰好不超过

        S,开辟一个新的起点,继续加和,再将总的开辟数与M份数进行比较。

PS:感觉自己越来越适应计算思维,从一开始的一窍不通,到后面愿意花时间反复研究,自

  己的进步很明显。虽然我现在仍然和dalao有很大差距,但是我看到了希望。

   加油,Ziyang!

  

以上是关于最优子序列问题(减而治之 - 二分查找 - 分组)的主要内容,如果未能解决你的问题,请参考以下文章

分而治之是不是利用了最优子结构?

使用分而治之技术的二分查找

C语言中的分而治之二分查找

分而治之——返回数组

为啥二分搜索是一种分而治之的算法?

分治算法-二分查找