All of these
else if (16 < bmi <= 18.5) {
are wrong. They don't do what you mean them to do. To achieve the desired result, use
else if (16 < bmi && bmi <= 18.5) {
The reason is, your expressions are evaluated as
else if ((16 < bmi) <= 18.5) {
where (16 < bmi) evaluates to true or false which in turn equals 1  or 0, and is then compared to the second constant. Reason why it is evaluated like so, is because the comparison operators are left-associative, thus are evaluated left-to-right.
Edit 2
Obligatory SO link: Is (4 > y > 1) a valid statement in C++? How do you evaluate it if so?
Edit
I suspected this one, but didn't know the formula. Now @MOehm has confirmed it (and wikipedia seems to confirm this as well):
bmi = (weight/(height/100)*(height/100));
should become
bmi = (weight/((height/100)*(height/100)));
The reason here is pretty much the same: operator precedence and expression evaluation rules in C++. OP, pay attention to these aspects and put parentheses where appropriate!
Edit 3 Here's how I'd go about this using STL (this approach has the benefit of clearly expressing the idea behind the algorithm, without burying it beneath the implementations details):
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <limits>
#include <algorithm>
int main()
{
    std::vector<std::pair<float, std::string> > bmi_table = {
        { 16, "Severely Underweight" },
        { 18.5, "Underweight" },
        { 25, "Healthy" },
        { 30, "Overweight" },
        { std::numeric_limits<float>::max(), "Severely Overweight" }
    };
    float height, weight;
    std::cin >>  height >> weight;
    const float bmi = (weight/((height/100.f)*(height/100.f)));
    const auto idx =
        std::find_if(bmi_table.begin(),
                     bmi_table.end(),
                     [&](decltype(bmi_table)::value_type& p) -> bool { return p.first > bmi; });
    std::cout << idx->second << '\n';
    return 0;
}