程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 2016 年青島網絡賽---Sort(k叉哈夫曼),2016---sort

2016 年青島網絡賽---Sort(k叉哈夫曼),2016---sort

編輯:C++入門知識

2016 年青島網絡賽---Sort(k叉哈夫曼),2016---sort


題目鏈接

http://acm.hdu.edu.cn/showproblem.php?pid=5884

 

Problem Description Recently, Bob has just learnt a naive sorting algorithm: merge sort. Now, Bob receives a task from Alice.
Alice will give Bob N sorted sequences, and the i-th sequence includes ai elements. Bob need to merge all of these sequences. He can write a program, which can merge no more than k sequences in one time. The cost of a merging operation is the sum of the length of these sequences. Unfortunately, Alice allows this program to use no more than T cost. So Bob wants to know the smallest k to make the program complete in time.   Input The first line of input contains an integer t0, the number of test cases. t0 test cases follow.
For each test case, the first line consists two integers N (2≤N≤100000) and T (∑Ni=1ai<T<231).
In the next line there are N integers a1,a2,a3,...,aN(∀i,0≤ai≤1000).   Output For each test cases, output the smallest k.   Sample Input 1 5 25 1 2 3 4 5   Sample Output 3   Source 2016 ACM/ICPC Asia Regional Qingdao Online     Recommend wange2014   |   We have carefully selected several similar problems for you:  5891 5890 5889 5887 5886    題意:to組數據,每次輸入N,T,然後輸入N個數,進行合並操作,將其中k個數合並為一個數後,代價為這k個數的和,並將這個和放入剩余的數列中,一直合並下去......最後合並為一個數,要求總的代價不超過T,求最小的k值;   思路:k叉哈夫曼樹,很明顯k值在2~N之間,而且k越大總的代價越小,那麼利用這個性質我們可以對k值進行二分查找,我開始時想的用優先隊列做,但超時了......我們可以對數組先從小到大排序,然後利用一個隊列裝合並得到的數,每次取數組和隊列中較小的數,注意用一個變量pos記錄數組取完數後的下一個位置,隊列中取完數後要刪除這個數,為什麼可以這樣呢? 因為每次合並得到的數一定小於等於上次合並得到的數,所以最小數一是 數組pos位置和隊列首中的較小者。另外,這些數的個數不一定滿足k個k個的合並,所以要先合並不足的幾個數,什麼時候不滿足呢,(N-1)%(k-1)!=0 時;   代碼如下:
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <queue>
#include <cmath>
#include <string.h>
using namespace std;
int N;
long long T;
long long a[100005];

int calc(int k)
{
    queue<long long>q;
    int pos=0;
    long long sum=0;
    if((N-1)%(k-1)!=0&&N>k) ///如果不能k個k個合並到底,則先合並籌不足k個的;
    {
        pos=(N-1)%(k-1)+1;
        for(int i=0;i<pos;i++)  sum+=a[i];
        q.push(sum);
    }
    while(1)
    {
        long long sum2=0;
        for(int i=0; i<k; i++)
        {
            if(!q.empty())
            {
                if(pos<N&&q.front()>a[pos])
                {
                    sum2+=a[pos];
                    sum+=a[pos];
                    pos++;
                }
                else
                {
                    sum2+=q.front();
                    sum+=q.front();
                    q.pop();
                }
            }
            else if(pos<N)
            {
                sum2+=a[pos];
                sum+=a[pos];
                pos++;
            }
            else goto endw;
        }
        if(sum>T) return 0;
        if(pos<N||!q.empty())
        q.push(sum2);
    }
    endw:;
    if(sum<=T) return 1;
    else    return 0;
}

int main()
{
    int to;
    scanf("%d",&to);
    while(to--)
    {
        scanf("%d%lld",&N,&T);
        for(int i=0; i<N; i++)
            scanf("%lld",&a[i]);
        sort(a,a+N);
        int l=2,r=N,mid;
        while(l<=r)
        {
            mid=(l+r)>>1;
            int f=calc(mid);
            if(f==0) l=mid+1;
            else     r=mid-1;
        }
        printf("%d\n",l);
    }
    return 0;
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved