#include <iostream>
#include <fstream>
#include <algorithm>
#include <queue>
using namespace std;
/*
首先找到向量y,使y = max{ y<=m| y(2)*1 + y(3)*2 + ... + y(n)*(n-1) = n-1 }。
如果找不到,则问题无解,否则用向量y作贪心计算
贪心策略:每次选最小的k堆进行合并,这个k应该最大
*/
const int MAX = 50;
int stone[MAX];
int m[MAX];
int y[MAX]; //y[i]记录合并n-i堆石子需要的次数,下标从0开始
int min(int a, int b)
{
return a<b? a:b;
}
bool found = false;
void search(int i, int sum, int n)
{
if(i == n-1)
{
if(sum == n-1) //总共合并的次数
found = true;
return ;
}
int temp = n / (n - i -1);
int max = min(temp, m[n-i]); //一次合并n-i堆石子最多可以合并的次数
int j;
for(j=max; j>=0; j--)
{
y[n-i] = j; //合并n-i堆石子需要的次数
sum += y[n-i]*(n-i-1);
search(i+1, sum, n);
if(found)
return;
sum -= y[n-i]*(n-i-1);
y[n-i] = 0;
}
}
int greedy(int n)
{
priority_queue<int, vector<int>, greater<int> > q;
int i;
for(i=1; i<=n; i++)
q.push(stone[i]);
int sum = 0;
int min = 0;
int j, k;
for(i=2; i<=n; i++) //一次可以合并的石子堆数
for(j=1; j<=y[i]; j++) //可以合并的次数
{
min = 0;
for(k=1; k<=i; k++)
{
min += q.top();
q.pop();
}
q.push(min);
sum += min;
}
return sum;
}
int main()
{
ifstream fin("Huffman变形.txt");
cout << "输入石子堆数:";
int n;
fin >> n; cout << n;
cout << "\n输入各堆石子个数:\n";
int i;
for(i=1; i<=n; i++)
{
fin >> stone[i];
cout << stone[i] << " ";
}
for(i=2; i<=n; i++)
{
cout << "\n输入一次合并" << i << "堆最多可以合并的次数:";
fin >> m[i];
cout << m[i] << " ";
}
y[1] = 0;
int sum = 0;
search(0, sum, n);
cout << "经计算:\n";
for(i=2; i<=n; i++)
if(y[i])
cout << "合并" << i << "堆石子" << y[i] << "次\n";
cout << "\n最小费用为:" << greedy(n);
cout << endl;
cout << endl;
fin.close();
return 0;
}
多元Huffman编码变形
最新推荐文章于 2020-12-10 16:58:59 发布