E - 最优合并问题
Description
给定k 个排好序的序列s1 , s2,……, sk , 用2 路合并算法将这k 个序列合并成一个序列。假设所采用的2 路合并算法合并2 个长度分别为m和n的序列需要m + n -1次比较。试设计一个算法确定合并这个序列的最优合并顺序,使所需的总比较次数最少。
为了进行比较,还需要确定合并这个序列的最差合并顺序,使所需的总比较次数最多。
对于给定的k个待合并序列,计算最多比较次数和最少比较次数合并方案。
Input
输入数据的第一行有1 个正整数k(k≤1000),表示有k个待合并序列。接下来的1 行中,有k个正整数,表示k个待合并序列的长度。
Output
输出两个整数,中间用空格隔开,表示计算出的最多比较次数和最少比较次数。
Sample
Input
4
5 12 11 2
Output
78 52
题解:
哈夫曼问题,分别取最大值做哈夫曼树和最小值做哈夫曼树,然后带权节点*路径长度的和就是最多比较次数与最少比较次数。
涉及哈夫曼问题可用优先队列(堆)进行解题,由于考试无法使用优先队列,所以后面会补一个不用优先队列的代码。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
using namespace std;
int maxn = 1050;
int main()
{
int n;
int i, MAX, MIN, sum;
int a[maxn];
scanf("%d",&n);
for(i=0; i<n; i++){
scanf("%d",&a[i]);
}
priority_queue<int> q1;
priority_queue<int, vector<int>, greater<int> > q2;
for(i=0; i<n; i++){
q1.push(a[i]);
q2.push(a[i]);
}
MAX = 0;
while(!q1.empty()){
sum = q1.top();
q1.pop();
if(q1.empty()){
break;
}
sum += q1.top();
q1.pop();
q1.push(sum);
MAX += sum - 1;
}
MIN = 0;
while(!q2.empty()){
sum = q2.top();
q2.pop();
if(q2.empty())
break;
sum += q2.top();
q2.pop();
q2.push(sum);
MIN += sum - 1;
}
printf("%d %d\n",MAX,MIN);
return 0;
}
模拟哈夫曼树建树过程求解。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
struct tree{
int l, r, f;
int data;
};
int maxn = 2050;
int INF = 0x3f3f3f3f;
int main(){
int MIN, MAX;
int n, i, j, m1, m2, c1, c2, t;
int a[maxn];
tree b[maxn];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(i=0; i<n-1; i++){
for(j=0; j<n-i-1; j++){
if(a[j] > a[j + 1]){
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
for(i=1; i<=n; i++){
b[i].data = a[i-1];
b[i].f = b[i].l = b[i].r = 0;
}
for(i=n+1; i<=2*n-1; i++){
c1 = c2 = 0;
m1 = m2 = INF;
for(j=1; j<i; j++){
if(!b[j].f){
if(b[j].data<m1){
m2 = m1;
m1 = b[j].data;
c2 = c1;
c1 = j;
}
else if(b[j].data<m2){
m2 = b[j].data;
c2 = j;
}
}
}
b[i].data = m1 + m2;
b[i].f = 0;
b[i].l = c1;
b[i].r = c2;
b[c1].f = b[c2].f = i;
}
MIN = 0;
for(i=1; i<=n; i++){
int q = i;
int p = 0;
while(b[q].f){
p++;
q = b[q].f;
}
MIN += b[i].data * p;
}
MIN -= (n - 1);
MAX = 0;
for(i=n-1; i>=1; i--){
a[i-1] += a[i];
MAX += a[i-1];
}
MAX -= (n - 1);
printf("%d %d\n",MAX, MIN);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
2018-10-20 HDU-1114_Piggy-Bank
2018-10-20 HDU_1087-Super Jumping! Jumping! Jumping!