多元Huffman编码变形—回溯法
2024-08-28 11:10:49
一、问题描述
描述
在一个操场的四周摆放着n堆石子。现要将石子有次序地合并成一堆。规定在合并过程中最多可以有m(k)次选k堆石子合并成新的一堆,2≤k≤n,合并的费用为新的一堆的石子数。试设计一个算法,计算出将n堆石子合并成一堆的最小总费用。 对于给定n堆石子,计算合并成一堆的最小总费用。
输入
输入数据的第1 行有1 个正整数n(n≤100),表示有n 堆石子。第2行有n个数,分别表示每堆石子的个数。第3 行有n-1 个数,分别表示m(k)(2≤k≤n)的值。
输出Output
将计算出的最小总费用输出。问题无解时输出“No solution!”
Sample Input
7
45 13 12 16 9 5 22
3 3 0 2 1 0
Sample Output
136
问题分析
- 首先用分支界限法(回溯法)找出每次合并石子堆数和可用次数
v[i]
- 然后对石子从小到大排序,每次取最小堆数合并石子(这样保证越往后合并的堆数就越多)
- 这样就就可以保证最小输出
代码
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int p[201];
int m[101];
int v[101];
/**
分支界限法 找出每次合并石子堆数和可用次数
参数:第i次合并,还剩余sum堆石子
*/
bool branch(int i,int sum){
if(i==1){
if(sum==1)
return true;
else
return false;
}
for(int j=m[i];j>=0;j--){
v[i] = j;
if(sum-v[i]*(i-1)<=0){
continue;
}
if(branch(i-1,sum-v[i]*(i-1))){
return true;
}
}
return false;
}
/**
把数组P中的第n-1个数据,插入到i到n-2数据里,
相当于把i到n从小到大排序
*/
void my_sorted(int i){
for (int j = n-1; j >= i; --j) {
if(p[j]<p[j-1]){
swap(p[j],p[j-1]);
}
else
break;
}
}
int main(){
cin>>n;
for (int i = 0; i < n; ++i) {
cin>>p[i];
}
for (int i = 2; i <= n; ++i) {
cin>>m[i];
}
//判断是否有解,并且把每次需要合并多少堆石子求出来
if(!branch(n,n)){
cout<<"No solution!"<<endl;
return 0;
}
sort(p,p+n);
// for(int i=0;i<=n;i++){
// cout<<v[i]<<' ';
// }
// cout<<endl;
int min = 0;
int start = 0;
int num = n;
for (int i = 1; i <= num;i++) {
for(int k = 0;k < v[i];k++){
int min2 = 0;
for (int j = 0; j < i; ++j) {
min2 += p[start++];
}
p[n++] = min2;
min += min2;
my_sorted(start);
}
}
cout<<min<<endl;
}
最新文章
- easyUI 如何不跳转页面,只是加载替换center部分内容
- ssh myeclipse的bug
- Kinect For Windows V2开发日志五:使用OpenCV显示彩色图像及红外图像
- ORACLE之表
- hibernate 使用C3P0数据源
- RHEL7重置root密码
- SRM 390(1-250pt)
- zsh-替换掉黑白的控制台
- 实用chrome插件
- sql差异
- Linux 环境下程序不间断运行
- python学习-抓取知乎图片
- Python3.6.2安装pip install paramike模块报错
- 添加浏览器back操作时的响应事件
- Next Permutation leetcode java
- jquery下拉菜单
- (原)android修改文件所属的用户组
- 查看mobileprovision信息
- cmd命令 从C盘转到D盘
- OpenGL视图--gluPerspective glOrtho glFrustum gluLookAt