算法第四章作业

你对贪心算法的理解:

 贪心算法就是满足局部最优解的时候同时可以满足全局最优解,然后对于局部的情况,贪心地选择当下最优的解,以此来得到最终的最优解。

请选择一道作业题目说明你的算法满足贪心选择性质:

 题目描述:

4-3 最优合并问题 (100分)
 

题目来源:王晓东《算法设计与分析》

给定k 个排好序的序列, 用 2 路合并算法将这k 个序列合并成一个序列。 假设所采用的 2 路合并算法合并 2 个长度分别为m和n的序列需要m+n-1 次比较。试设 计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。 为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。

输入格式:

第一行有 1 个正整数k,表示有 k个待合并序列。 第二行有 k个正整数,表示 k个待合并序列的长度。

输出格式:

输出最多比较次数和最少比较次数。

输入样例:

在这里给出一组输入。例如:

4
5 12 11 2 
 

输出样例:

在这里给出相应的输出。例如:

78 52
代码:

 

//#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
#define infll 0x3f3f3f3f3f3f3f3f
#define il inline
#define re register
#define pb push_back
#define db double
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define puu pair<ull,ull>
#define MP make_pair
#define lowbit(x) x&(-x)
#define fi first
#define se second
il ll read()
{
    char ch = getchar();
    ll p = 1,data = 0;
    while(ch<'0'||ch>'9')
    {
        if(ch == '-')p = -1;
        ch = getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        data = data*10+(ch^48);
        ch = getchar();
    }
    return p*data;
}
il ll qpow(ll a,ll b)
{
    ll r = 1;
    while(b)
    {
        if(b&1)r = a*r;
        a = a*a;
        b>>=1;
    }
    return r;
}
il ll gcd(ll a,ll b)
{
    if(!a || !b) return (!a)?b:a;
    while(b ^= a ^= b ^= a %= b);
    return a;
}
il ll lcm(ll a,ll b)
{
    return a*b/gcd(a,b);
}
void exgcd(ll a, ll b, ll &x,ll &y)
{
    if(!b) x = 1, y = 0;
    else
    {
        exgcd(b, a % b, y, x);
        y -= x * (a / b);
    }
}
const int mod = 1e9+7;
int main()
{
    int n = read();
    priority_queue<ll> q;
    priority_queue<ll,vector<ll>,greater<ll> > p;
    for(int i = 1; i <= n; i++)
    {
        ll x = read();
        q.push(x);
        p.push(x);
    }
    pll ans = {0,0};
    while(q.size() != 1)
    {
        ll t = q.top();
        q.pop();
        t += q.top();
        q.pop();
        q.push(t);
        ans.fi += t-1;
    }
    while(p.size() != 1)
    {
        ll t = p.top();
        p.pop();
        t += p.top();
        p.pop();
        p.push(t);
        ans.se += t-1;
    }
    printf("%lld %lld\n",ans.fi,ans.se);
    return 0;
}
View Code

 

 

算法思想:对于每一次合并,贪心地选择长度最小(最大)的两个进行合并。

证明1(最小):假设此时有三个长度不一的待合并序列,长度由小到大分别为a,b,c,那么则有 (a+b)+((a+b)+c) <= (a+c)+((a+c)+b) <= (b+c)+((b+c)+a),显然,此时选最小的两个即a,b进行合并是最小的,以此类推,最大同理

请说明在本章学习过程中遇到的问题及结对编程的情况

结对编程情况:旁观者清,结对编程更方便简单地就能找出代码中存在的bug。

posted @ 2020-11-15 00:16  Frantatic  阅读(153)  评论(0编辑  收藏  举报