高效算法设计_递归与分治(贷款,最大值最小化)

贷款

题目:一次向银行借a元钱,分b月还清。如果需要每月还c元,月利率是多少(按复利率计算)?

  • 例如借2000元,分4个月每月还510,则月利率为0.797%。答案应不超过100%。

输入:

2000 4 510

输出:

0.797%

思路:

  • 设月利率为x,则第一个月还钱后还需还a(1+x)-c,重复b个月后可以得到方程。
  • 利用f(x)和0的关系与x和方程解x0的大小关系等价。
    (虽然现对分治还是搞不懂,但是都有点看习惯了,分治-分而治之。)
  • 每个层次的递归都有三个步骤:分解,递归求解,合并。
    最基础的应用就是之前的归并排序

友情链接:

五大常用算法之一:分治算法
分治法-维基百科

void merge_sort(int array[],int first,int last)
{
int mid = 0;
if(first

#include <stdio.h>

int main() {
    double a,c,x=0,y=100;
    int b,i;
    scanf("%lf %d %lf",&a,&b,&c);
    while(y-x>1e-5){
        double m=x+(y-x)/2;//划分
        double f=a;
        for(int i=0;i<b;i++)
            f+=f*m/100.0-c;
        if(f<0) x=m;
        else y=m;
    }
    printf("%.3lf%%\n",x);
    return 0;
}

* 最大值最小化*

题目:把一个包含n个正整数的序列划分成m个连续的子序列。设第i个序列的各数之和为S(i),求所有S(i)的最大值最小是多少?

  • 序列1 2 3 2 5 4划分为3个子序列的最优方案为 1 2 3 | 2 5 | 4,其中S(1),S(2),S(3)分别为6,7,4,那么最大值为7;
    如果划分为 1 2 | 3 2 | 5 4,则最大值为9,不是最小。

输入:

6 3
1 2 3 2 5 4

输出:

7
#include <stdio.h>
int max=-10000;//元素中的最大值
int sum=0;//所有元素之和
int A[10010];
int m,n;
//是否能把序列划分为每个序列之和不大于x的m个子序列
bool is_part(int x)
{
    //每次往右划分,划分完后,所用的划分线不大于m-1个即可
    int line = 0, s = 0;
    for(int i = 0; i < n; i++)
    {
        if(s+A[i] > x)  //和大于x,不能再把当前元素加上了
        {
            line++;     //加一条分隔线
            s = A[i];
            if(line > m-1)  //分隔线已经超过m-1条
                return false;
        }
        else
        {
            s+=A[i];    //把当前元素与前面的元素连上,以便尽量往右划分,贪心到底
        }
    }
    return true;
}

int binary_solve()
{
    int l = max, r = sum;
    while (l < r)
    {
        int m = l + (r-l)/2;
        if (is_part(m)) r = m;
        else l = m + 1;
    }
    return l;
}
int main() {
    int i;
    scanf("%d%d",&n,&m);
    for(i=0;i<n;i++) {
        scanf("%d",&A[i]);
        if(A[i]>max) max=A[i];
        sum+=A[i];
    }
    int t=binary_solve();
    printf("%d",t);
    return 0;
}
    原文作者:递归与分治算法
    原文地址: https://blog.csdn.net/qq_31060183/article/details/77152662
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞