一系列文件的最短压缩时间

时间:2014-05-04 04:39:19

标签: algorithm math optimization dynamic-programming

有点算法问题,或者可能是优化问题,或动态编程。

我们说我们要压缩N个文件。 平均压缩比为L. 文件的压缩时间取决于两个因素 - 1.当前正在处理的文件的大小,以及 2.系统中剩余的内存空间(总计= M,占用=压缩和未压缩文件的文件大小之和)

所以

t(i) = K * s(i) / (M-L*(s(1)+s(2)+....+s(i))-(s(i+1) + s(i+2) + .....+ s(n))

其中s(i)是第i个文件的大小,t(i)是压缩第i个文件所用的时间。

我要做的是计算要压缩的文件的最佳系列,以便所需的总时间最短。那么如何计算该系列呢?

2 个答案:

答案 0 :(得分:2)

似乎最好的方法是按大小对文件进行排序并对其进行处理。这种贪婪的方法可以解释为“首先压缩小文件以避免在大文件后压缩它”。

可能的批准是:

  

如果我们有两个文件A,B这样大小(A)< = size(B)我们可以证明那个时间

     

t(A,B)< = t(B,A)

     

A / M + B /(M - L * A)< = B / M + B /(M - L * B)

     

A *(1 / M - 1 /(M - L * B))< = B *(1 / M - 1 /(M - L * A))

     

B / A> =(1 / M-1 /(M-L * B))/(1 / M-1 /(M-L * A))= B *(M-L * A) /(A *(M - L * B))

     

1> =(M-L * A)/(M-L * B)

     

-L * B> = -L * A

     

B> = A

     

所以这意味着第一个方程式也是正确的(如果没有在某处失败:D)

排序给我们保证A< B为每对文件。

我为N< = 10编写了O(N!)bruteforce。它为我能想到的每个测试提供了排序数组。

  

测试:N,L,M,K和N文件

     

8 0.5 80.0 1.0

     

7 1 6 3 4 5 6 5

     

结果:

     

0.515769

     

1 3 4 5 5 6 6 7

#include <iostream>
#include <algorithm>
using namespace std;

// will work bad for cnt > 10 because 10! = 3628800
int perm[] = {0,1,2,3,4,5,6,7,8,9};
int bestPerm[10];
double sizes[10];

double calc(int cnt, double L, double M, double K, double T) {
    double res = 0.0, usedMemory = 0.0;
    for(int i = 0; i < cnt; i++) {
        int ind = perm[i];
        res += K * sizes[ind] / (M - L * usedMemory - (T - usedMemory)); 
        usedMemory += sizes[ind];
    }
    return res;
}

int main() {
    int cnt;
    double L,M,K,T = 0.0;
    cin >> cnt >> L >> M >> K;
    for(int i = 0; i < cnt; i++)
        cin >> sizes[i], T += sizes[i];

    double bruteRes = 1e16;
    int bruteCnt = 1;
    for(int i = 2; i <= cnt; i++)
        bruteCnt *= i;
    for(int i = 0; i < bruteCnt; i++) {
        double curRes = calc(cnt, L, M, K, T);
        if( bruteRes > curRes ) {
            bruteRes = curRes;
            for(int j = 0; j < cnt; j++)
                bestPerm[j] = perm[j];
        }
        next_permutation(perm, perm + cnt);
    }
    cout << bruteRes << "\n";
    for(int i = 0; i < cnt; i++)
            cout << sizes[bestPerm[i]] << " ";
    cout << "\n";

    return 0;
}

已更新对于所有文件pastebin的L不同的情况的实现(看起来bruteforce更喜欢按压缩比L [i]的降序对它们进行排序并使用较小的文件首先,如果L相等)。

答案 1 :(得分:0)

假设您有一个声称最佳的计划。考虑任何文件和紧随其后处理的文件。如果您可以通过交换它们来改进计划,那么它可能不是最佳的。因此,如果您可以证明最好在大文件之前处理一个小文件,而这两个文件并排放置,那么您可以首先显示最佳日程安排的排序顺序,因为您可以改进任何其他文件时间表。

因为您只是交换两个相邻文件,所以在这两个文件之前和之后处理文件所花费的时间都没有改变 - 前后可用的内存量相同。您也可以扩展问题,以便其中一个文件大小为一个单位。假设您在第一个文件之前总共有K个单位的内存空闲,并且假设第二个文件的大小为x个单位且压缩比为1:L,则最终会得到类似1 / K + x /(K +)的内容L) - x / K - 1 /(K - xL)作为由于这对文件导致的压缩时间的差异 - 我的代数非常容易出错,但我认为这可以归结为像L ^ 2x(1- x)复杂但积极的东西,这表明对于一对文件,你总是想先压缩短文件,所以我之前说过的最好的时间表是按照最短文件的排序顺序。