算法第四章作业
你对贪心算法的理解:
贪心算法就是满足局部最优解的时候同时可以满足全局最优解,然后对于局部的情况,贪心地选择当下最优的解,以此来得到最终的最优解。
请选择一道作业题目说明你的算法满足贪心选择性质:
题目描述:
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; }
算法思想:对于每一次合并,贪心地选择长度最小(最大)的两个进行合并。
证明1(最小):假设此时有三个长度不一的待合并序列,长度由小到大分别为a,b,c,那么则有 (a+b)+((a+b)+c) <= (a+c)+((a+c)+b) <= (b+c)+((b+c)+a),显然,此时选最小的两个即a,b进行合并是最小的,以此类推,最大同理。
请说明在本章学习过程中遇到的问题及结对编程的情况
结对编程情况:旁观者清,结对编程更方便简单地就能找出代码中存在的bug。