[关闭]
@ysner 2018-08-10T14:43:33.000000Z 字数 1365 阅读 1822

哈夫曼树

总结


构建

每次选值(出现次数)最小的两个数,为他们构建一个共同的父结点,结点值为两数值之和。
然后不断地进行下去。

编码

从上往下,把左儿子路径标为,右儿子路径标为
每个叶子结点的编码为从叶子结点到根结点的标号字符串。

性质

应用

据说设表示第层,当前层还有个空结点,下一层还有个空结点是否作为终止结点即可。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<vector>
  8. #define re register
  9. #define il inline
  10. #define ll long long
  11. #define max(a,b) ((a)>(b)?(a):(b))
  12. #define min(a,b) ((a)<(b)?(a):(b))
  13. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  14. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  15. using namespace std;
  16. const int mod=1e9+7,N=800;
  17. int n,dp[2][N][N],s[N],a[N];
  18. il ll gi()
  19. {
  20. re ll x=0,t=1;
  21. re char ch=getchar();
  22. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  23. if(ch=='-') t=-1,ch=getchar();
  24. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  25. return x*t;
  26. }
  27. il bool cmp(re int x,re int y){return x>y;}
  28. int main()
  29. {
  30. freopen("epic.in","r",stdin);
  31. freopen("epic.out","w",stdout);
  32. n=gi();
  33. fp(i,1,n) a[i]=gi();sort(a+1,a+1+n,cmp);
  34. fq(i,n,1) s[i]=s[i+1]+a[i];
  35. re int now=0,nxt=1;
  36. memset(dp[now],127,sizeof(dp[now]));
  37. dp[now][1][0]=0;
  38. fp(i,0,n)
  39. {
  40. swap(now,nxt);
  41. memset(dp[now],127,sizeof(dp[now]));
  42. fp(j,0,n-i)
  43. fp(k,0,n-i-j)
  44. {
  45. if(dp[nxt][j][k]>2e9) continue;
  46. if(j) dp[now][j-1][k]=min(dp[now][j-1][k],dp[nxt][j][k]);
  47. dp[nxt][j+k][j]=min(dp[nxt][j+k][j],dp[nxt][j][k]+s[i+1]);
  48. }
  49. }
  50. printf("%d\n",dp[nxt][0][0]);
  51. fclose(stdin);
  52. fclose(stdout);
  53. return 0;
  54. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注