Convert it to a sorted array with minimum cost

http://shashank7s.blogspot.com/2011/05/wap-to-find-minimum-value-in-window-of.html


You are given an array of positive integers. Convert it to a sorted 
array with minimum cost. Only valid operation are 
1) Decrement -> cost = 1 
2) Delete an element completely from the array -> cost = value of 
element 
For example: 
4,3,5,6, -> cost 1 
10,3,11,12 -> cost 3 


we can make the DP more efficient You don't need to scan the whole previous column when calculating costs of decrementing. Rather there are only two 
possibilities. 

Algorithm Given By Gene

DP is better for this problem. 
Remember C(n, m) is the cost of making a[1 .. n] into a non-decreasing 
sequence with the last element being no more than m. And we always 
draw m from the set V of values in a. 
So here is the new DP: 
C(1, m) = max(a[1] - m, 0) // first row only decrement is possible 
C(n, m) = min ( 
a[n] + C(n - 1, m), // delete 
(a[n] <= m) ? C(n - 1, a[n]) : C(n - 1, m) + a[n] - m // decrement 

In case you don't follow, the "//delete" line is saying that we 
already know the cost of making everything up to element n-1 non- 
decreasing and no more than m. This, by recursive assumption, is just 
C(n-1,m). The additional cost of deleting a[n] is a[n]. 
The "//decrement" line is similar, but there are 2 cases. If a[n] is 
more than m, we must decrement it. The cost here consists of making 
everything up to n-1 non-decreasing and no more than m, i.e. C(n-1,m). 
Plus we have the cost of chopping a[n] down to m, which is a[n]-m. 
In the other case, a[n] is m or less. So there's no need to 
decrement, but we must get the elements a[1..n-1] to be no more than 
a[n]. Again by recursive assumption this cost is C(n-1,a[n]). 
Here is an example. Suppose we have a = [5, 1, 1, 1, 3, 1]. The 
least cost here is obtained by decrementing the 5 to 1 (cost 4) and 
deleting the final 1 (cost 1) for a total cost of 5. 
So let's try the algorithm. (You must view this with a fixed font.) 
Table of C(n, m) values: 
m = 1 3 5 
n = 1 : 4 2 0 
n = 2 : 4 3* 1* 
n = 3 : 4 4 2* 
n = 4 : 4 4 3* 
n = 5 : 6m 4 4 
n = 6 : 6 5* 5* 
Here * means C resulted from decrementing and "m" means that a 
decrement was based on the value of m rather than a[n]. 
We take the answer from C(6,5) = 5. 
Implementing this is a little tricky because m values are drawn from 
V. You could use a hash table for the m-axis. But it's more 
efficient to store V in an array and convert all the values of m in 
the DP into indices of V. Because all the indices lie in [ 1 .. | 
V| ], we can use simple arrays rather than hash tables to represent 
the rows of the table C. 
We only need 2 rows at a time, so O(|V|) storage does the job. 
For C, we also need to convert all the indices to origin 0. 
So here's the final O(n^2) code. I think this is a correct 
implementation. If anyone has an example that breaks it, I'd like to 
see. 


大体思想就是,f[n][m],在由数组a1...an中,组成的有序序列,的最后一个值不超过m

但是考虑到m会很大,用离散化


#define NMAX 10000 
int cost(int *a, int N) 
{ 
    int i, j, max, Nv; 
    int V[NMAX], A[NMAX], B[NMAX]; 
    int *Cm = A, *Cn = B; // (n-1)'th and n'th rows of C 
    // Compute set V with no duplicates. 
    // Remember where max element is. 
    Nv = max = 0; 
    for (i = 0; i < N; i++) { 
        for (j = 0; j < Nv; j++) 
            if (a[i] == V[j]) 
                break; 
        if (j == Nv) { 
            V[Nv++] = a[i]; 
            if (V[j] > V[max]) 
                max = j; 
        } 
        a[i] = j; // Convert a to indices. 
    } 
    // Fill in first row of C. 
    for (i = 0; i < Nv; i++) 
        Cm[i] = (V[a[0]] >= V[i]) ? V[a[0]] - V[i] : 0; 
    // Fill in the rest of the rows of C. 
    for (i = 1; i < N; i++) { 
        for (j = 0; j < Nv; j++) { 
            int del = Cm[j] + V[a[i]]; 
            int dec = (V[a[i]] <= V[j]) ? Cm[a[i]] : Cm[j] + V[a[i]] - V[j]; 
            Cn[j] = (del < dec) ? del : dec; 
        } 
        // Swap row buffers so current becomes previous. 
        int *tmp = Cn; Cn = Cm; Cm = tmp; 
    } 
    return Cm[max]; 
} 

int main(void) 
{ 
    static int a[] = { 5, 1, 1, 1, 3, 1 }; 
    printf("Min cost = %d\n", cost(a, sizeof a / sizeof a[0])); 
    return 0; 
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值