码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-12-11 23:26:42      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:ddl   main   数组   null   计算   部分   col   free   dal   

技术图片

 

 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\n",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!

  

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

标签:ddl   main   数组   null   计算   部分   col   free   dal   

原文地址:https://www.cnblogs.com/ziyang1060/p/12026405.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!