首页 > 代码库 > HDU 5884 (贪心)

HDU 5884 (贪心)

problem sort

题目大意

  有n个数组,每个数组有a[i]个元素,每次可以将至多k个数组合并为一个数组,所花费代价为这些数组的元素和。给定代价上限,求将所有数组合并为1个数组的最小k。

解题分析  

  二分k后就成了k叉哈夫曼树问题。

  对于k叉哈夫曼树,可以利用所合并元素的权值单调性,用两个双端队列来实现。

  另外,如果(n-1)%(k-1) != 0 , 则需要另外在补上(k-1) - (n-1)%(k-1)个0。

参考程序

技术分享
  1 #include <map>  2 #include <set>  3 #include <stack>  4 #include <queue>  5 #include <cmath>  6 #include <ctime>  7 #include <string>  8 #include <vector>  9 #include <cstdio> 10 #include <cstdlib> 11 #include <cstring> 12 #include <cassert> 13 #include <iostream> 14 #include <algorithm> 15 #pragma comment(linker,"/STACK:102400000,102400000") 16 using namespace std; 17  18 #define N 100008             19 #define M 50008     20 #define LL long long 21 #define lson l,m,rt<<1 22 #define rson m+1,r,rt<<1|1  23 #define clr(x,v) memset(x,v,sizeof(x)); 24 #define bitcnt(x) __builtin_popcount(x) 25 #define rep(x,y,z) for (int x=y;x<=z;x++) 26 #define repd(x,y,z) for (int x=y;x>=z;x--) 27 const int mo  = 1000000007; 28 const int inf = 0x3f3f3f3f; 29 const int INF = 2000000000; 30 /**************************************************************************/  31  32 int T; 33 int n,limit; 34 int a[N*10],b[N*10],c[N*10]; 35  36 int check(int k) 37 { 38     //printf("%d\n",k ); 39     int tmp=((k-1)-(n-1) % (k-1)) % (k-1); 40     int m=n+tmp; 41     rep(i,1,tmp) b[i]=0; 42     rep(i,tmp+1,m) b[i]=a[i-tmp]; 43     LL s=0; 44     int i=1,l=1,r=0,op=0,sum=0; 45     while (i<=m) 46     { 47         if (l>r || b[i]<=c[l]) 48         { 49             op++; 50             sum+=b[i]; 51             i++; 52         } 53         else 54         { 55             op++; 56             sum+=c[l]; 57             l++; 58         } 59         if (op==k) 60         { 61             s+=sum; 62             c[++r]=sum; 63             op=sum=0; 64         } 65     } 66     while (l<=r) 67     { 68         op++; 69         sum+=c[l]; 70         l++; 71         if (op==k) 72         { 73             s+=sum; 74             c[++r]=sum; 75             op=sum=0; 76         }     77     } 78     //rep(i,1,m)  printf("%d ",b[i]); printf("\n"); 79     //rep(i,1,r)  printf("%d ",c[i]); printf("\n"); 80     if (op!=1) s+=sum; 81     //printf("%lld\n",s ); 82     return s<=limit; 83 } 84  85 int cmp(int x,int y) 86 { 87     return x>y; 88 } 89 int main() 90 { 91     scanf("%d",&T); 92     while (T--) 93     { 94         scanf("%d%d",&n,&limit); 95         rep(i,1,n) scanf("%d",&a[i]); 96         sort(a+1,a+n+1); 97         int l=2,r=n,mid,res; 98         while (l<=r) 99         {100             mid=(l+r)/2;101             if (check(mid))102             {103                 res=mid;104                 r=mid-1;105             }106             else l=mid+1;107         }108         printf("%d\n",res);109     }110 }
View Code

 

HDU 5884 (贪心)