3

Weights of n men and their strengths (max weight they can carry) are given. Height of all are same and given. Find the maximum height they can make by standing on each other? That means, you have to place them by taking maximum number of men from them, such that no men is carrying weight more than his strength.

This question is bugging me. First I thought using greedy, by taking person of maximum strength first, but it is not giving correct answer. Then I tried to solve it, like knapsack, which is also not right. I am not able to come up with an efficient algorithm. Can anyone help?

Jongware
  • 22,200
  • 8
  • 54
  • 100
nits
  • 31
  • 2
  • You can mentally simplify this a bit by taking out the height parameter ("Height of all are same"). Can you give an example of your Greedy solution, and why it does not give a correct answer? – Jongware May 06 '15 at 09:09
  • How do they stand on each others? do they form a triangle, where each man stands over 2 shoulders of 2 adjacent men in the below level? – Khaled.K May 06 '15 at 09:17
  • I'm pretty sure this is NP complete. In the variable-height case, I've found a simple reduction from subset sum to this problem. I'm pretty sure a similar argument can be found for the fixed-height case. – user2357112 May 06 '15 at 09:18
  • Actually, I'm starting to think the fixed-height case might be way easier than the variable-height case. I've got an idea about how to do it by always adding the person that maximizes the carrying capacity of the overall stack. – user2357112 May 06 '15 at 09:47
  • Hmm. Doesn't quite work if you greedily add the carrying capacity maximizer, but there can be at most one other guy beneath him. That at least reduces the effective depth of the search tree, but I haven't figured out if it can be applied to produce a polynomial time algorithm. – user2357112 May 06 '15 at 10:02
  • Isn't a trivial solution to scan through the n! permutations of the men-stack, and choose the highest tower? – ysap May 09 '15 at 16:37

1 Answers1

0

First of all sorry by my english :)

Here is one way that you can think as a way to solve the problem.

Ok if you can supposed that each floor absorbs the whole weight in a uniform form, ( I mean there are no restriction like "one man can carry only the weight of two mens" or somethin like that..). We will start with an hypothetical structure which has one man for each floor, and with that structure we will start to check the restrictions and arrange people.

We will check the lowest floor (first floor), and we will ask: Can this floor handle the weight of all the higher floors?
If the answer is no, we remove one men from the top of the tower and we add it to this floor, and we check again the weight condition on this floor. If the answer is yes, we pass to check the next floor.

After that we will have an structure which meet the requirements. And the C# code:

int amountOfMens    = n;
float weight        = w;
float strength      = s;
float height        = h;
int []mensInEachFloor;


public void MyAlg()
{
    mensInEachFloor = new int[ amountOfMens ]; // the max height that we can achieve is the max amount of mens.

    for(int i=0; i < mensInEachFloor.Length; i++ )
    {
        // we put one men on each floor, just to check if the highest heigth is achivable 
        mensInEachFloor[i] = 1;
    }

    // now we start to use our algorithm
    // for each floor:
    for(int i = 0; i < mensInEachFloor.Length; i++ )
    {
        // for each floor we will work on it until supports its designed weight 
        bool floorOk = false;

        while(! floorOk)
        {
            // we check if the weigth of all the higher floors can be supported by this level
            float weightToBeSupported       = TotalWeightOfHigherFloors(i+1);
            float weightThatCanBeSupported  = WeightHandledByFloor(i);

            if( weightToBeSupported > weightThatCanBeSupported )
            {
                // Remove one men from the top 
                RemoveOneManFromHighestFloor();
                // add one men to this floor to help with the weight
                AddOneManToFloor(i);
            }
            else
            {
                // we are ok on this floor :)
                floorOk = true;
            }
        }
    }

    Debug.Log("The total heigth of the tower is : " + GetTowerHeight() );
}

private float TotalWeightOfHigherFloors(int startingFloor)
{
    float totalWeight = 0;
    for(int i= startingFloor; i< mensInEachFloor.Length; i++ )
    {
        totalWeight += mensInEachFloor[i] * weight;
    }

    return totalWeight;
}

private float WeightHandledByFloor(int floor)
{
    return mensInEachFloor[floor] * strength;   
}

private void RemoveOneManFromHighestFloor()
{
    // we start to see from the top..
    for(int i = mensInEachFloor.Length - 1 ; i >= 0; i-- )
    {
        // if on this floor are one or more mens..
        if(mensInEachFloor[i] != 0)
        {
            // we remove from the floor
            mensInEachFloor[i] = mensInEachFloor[i] - 1;
            // and we are done
            break;
        }
    }
}

private void AddOneManToFloor(int floor)
{
    // Add one man to the selected floor
    mensInEachFloor[floor] = mensInEachFloor[floor] + 1;
}

private float GetTowerHeight()
{
    // We will count the number of floors with mens on it
    float amountOfFloors = 0;
    for(int i= 0; i< mensInEachFloor.Length; i++ )
    {
        // If there are more than zero mens
        if( mensInEachFloor[i] > 0 )
        {
            // it means that it is a valid floor
            amountOfFloors++;
        }
    }

    // number of floors times height
    return amountOfFloors * height;

}

Cheers !

mayo
  • 3,845
  • 1
  • 32
  • 42