Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 一系列文件的最短压缩时间_Algorithm_Math_Optimization_Dynamic Programming - Fatal编程技术网

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

Algorithm 一系列文件的最短压缩时间,algorithm,math,optimization,dynamic-programming,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个文件所用的时间 我要做的是计算要压缩的文件的最佳序列,以使所需的总时间最小。那

一个位算法问题,或者可能是优化问题,或者是动态规划问题

假设我们有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个文件所用的时间


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

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

可能的批准是:

如果我们有两个文件A,B,大小(A)=A

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

排序可以保证每对文件的A
我写了O(N!)假设你有一个被认为是最优的时间表。考虑任何文件和它之后处理的一个文件。如果你可以通过交换它们来改进进度表,它就不是最优的。因此,如果你能证明,当两个并排的时候,在一个大文件之前处理一个小文件总是最好的,那么你可以显示出一个小文件。最佳时间表是以最小的文件优先排序的,因为您可以改进任何其他时间表


因为您只是在交换两个相邻的文件,所以在这两个文件之前和之后处理文件所需的时间没有改变-前后可用的内存量相同。您不妨将问题扩展到一个文件大小为一个单位。假设在第一个文件之前,您总共有K个单位的可用内存,假设第二个文件的大小为x个单位,压缩比为1:1,那么由于这对文件的压缩时间不同,最终的结果是1/K+x/(K+L)-x/K-1/(K-xL)——我的代数非常容易出错,但我认为这可以归结为L^2x(1-x)在一些复杂但积极的事情上,这表明对于一对文件,你总是希望先压缩短文件,所以根据我前面所说的,最好的时间表是以最短文件为先排序。

听起来有点像家庭作业,不是吗?听起来有点像,但不是。这是我在考虑练习时想到的关于DP的问题。首先,似乎最佳策略是首先压缩最大的文件。@Ante实际上恰恰相反。请查看Ralor的回答:)
res+=K*size[ind]/(M-L*usedMemory-(T-usedMemory))
其中
T
是文件的总大小。但是,即使这样,输出也是按升序排列的。谢谢我想知道你是否能提出一些可以折衷的修改建议,升序或降序都不是最优的。@k_程序员我修正了它。它并没有太大的变化,因为它就像读取值后的倒L=1-L和取代基M-=t。我的第一个想法是尝试按升序和降序,或者通过三元搜索找到一些中间位置“k”,并将所有文件分成两组,但我发现它没有用。我的朋友说,当所有文件的L都相同时,这个问题很简单,但我们都认为上面显示的批准是正确的。您可以尝试在10^6个随机(但正确)数据集上运行bruteforce,并检查答案是否会在所有数据集中排序。变量L呢?让我试着用变量L来改变L:),它给出了一个既不升序也不降序的序列——这正是我想要的!但现在的问题是如何动态计算最优序列(使用DP等)?@k_程序员我用pastebin链接更新了帖子,当L[I]不同时问题仍然很容易)贪婪仍然获胜)是的,看起来是这样,Ralor的回答几乎证明了这一点。很好的解释!但是,如果你建议对问题本身进行一些修改,使最佳顺序不是升序或降序,那就太好了。
#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;
}