Processing math: 100%

Sunday, September 28, 2014

a bit of greedy: SPOJ - CHOCOLA

Problem Statement
SPOJ - CHOCOLA

Solution:
Greedy Algorithm: We choose the highest cost cut each time until no cut is left.
Proof of optimality:
Firstly notice that the number of cuts needed no matter how we do the cutting is C(n,m) = n+m+n*m, and this can be easily proven by induction. So the total number of cuts is always the same. Now the problem asked us to minimize the cost function S=a1w1+a2w2++aNwN where wi is the cost of cutting a certain edge, while ai is the corresponding coefficients. The coefficient ai is determined by the total number of cuts we done using edge wi at the end of the cutting process. Notice that sum of the coefficients are always constant, hence we want to find a distribution of ai obtainable such that S is minimum. To do so we claim that by performing cuts on highest cost edge as early as possible, we can reach optimal S. If we encounter several edges having the same cost, we can cut any one of them first, since in the end we will cut them all up as early as possible, hence end up with the same coefficient ai. The proof goes as follows:
Without loss of generality let w1w2w3wN.  Let O be another optimal cutting of S that have same coefficients different from that of S. Let wm be the highest cost edge such that the coefficient in O does not tally with that of S. This means that am in O will definitely be larger than that of S, since the one in S is the smallest possible am obtainable as we do the cutting as early as possible. Indeed, if am is smaller, then we have 2 cases:
1. Some of ai in O before am are bigger or smaller than that of S as the result. Then this contradicts the fact that am is the first to deviate from S.
2. None of ai in O is affected by the deviation in am. This is only possible if the cut wm is independent of the cut made in wi before wm. But that only means that am is already the minimum possible, hence to have a smaller value will be a contradiction.
Hence am must be bigger, and hence there are some aj after am in O that are smaller as the result to make up the difference. This difference is over wj which are smaller than wm, hence in the end we will have S<O, a contradiction since O is optimal. Hence S must have been optimal in the first place.



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

/* SPOJ: CHOCOLA
Idea: Greedy Algorithm Stays Ahead
The number of breaks needed is always the same.
#Proof:
C(n,m) = n + m + n*m
C(0,0) = 0 (a single box choclate needs 0 cut)
Cut horizontally:
C(n,m) = 1 + C(a,m) + C(b,m) such that a+b+1 = n
C(n,m) = 1 + a+m+a*m + b+m+b*m
       = 1 + (n-1) + 2*m + (n-1)*m
       = n + m + n*m   :)
equally for vertical cut
#
Observation: the problem is similar to weight distribution problem
Observation: each cut will happen sooner or later
Observation: the "weight" of a cut is non decreasing
Observation: if a vertical and horizontal cost are equal, cutting 
order does not matter. Proof?
So we greedily choose the largest cut-cost each time
*/

int x[1003], y[1003];

int main(){
    int tc;
    cin >> tc;
    while(tc--){
        int m,n;
        cin >> m >> n;
        for(int i=1;i<m;++i){
            cin >> x[i];
        }
        for(int i=1;i<n;++i){
            cin >> y[i];
        }
        int h = 1,v=1;
        sort(x+1,x+m);
        reverse(x+1,x+m);
        sort(y+1,y+n);
        reverse(y+1,y+n);
        int i=1,j=1;
        int ans = 0;
        while(i<m && j<n){
            if(x[i] > y[j]){
                ans += x[i]*v;
                ++h;
                ++i;
            } else {
                ans += y[j]*h;
                ++v;
                ++j;
            }
        }
        if(i<m){
            int sum = 0;
            while(i<m){
                sum += x[i];
                ++i;
            }
            ans += sum*v;
        } else {
            int sum = 0;
            while(j<n){
                sum += y[j];
                ++j;
            }
            ans += sum*h;
        }
        cout << ans << endl;
    }
    return 0;
}

1 comment: