HalvingGridSearchCV giving non-optimal results with min_resources='exhaust'

### Describe the bug

I am using `HalvingGridSearchCV` with 160 combinations and 1050 samples. When I use `min_resources` with `'exhaust'`, I get 6 iterations with the last iteration including 5 candidates and 640 samples. The process starts with 20 samples.

When I set `min_resources=30`, I also get 6 iterations with the last iteration having 5 candidates, but with 960 samples.

### Steps/Code to Reproduce

```python
halving_cv = HalvingGridSearchCV(
    knn_model, knn_grid,  #our model and the parameter combos we want to try
    scoring="roc_auc",  #could alternatively choose f1, accuracy or others
    n_jobs=-1,  #use all available cpus
    min_resources=30,  #"exhaust" sets this to 20, which is non-optimal. Possible bug in algorithm.
    factor=2,  #double samples and take top half of combos on each iteration
    cv=5, random_state=1234,
    refit=True,  #remembers the best combo and gives us back that model already trained and ready for testing
)

grid_result = halving_cv.fit(x_train, y_train)
```

### Expected Results

My understanding is that by using 'exhaust', the algorithm should figure out that 30 is a better value for min_resources. Instead it sets it to 20.

My ideal case would be for the last iteration to use all 1050 samples with the 5 candidates but I see no way to set parameters to make this happen.

My question is whether there is a bug in the min_resources=exhaust algorithm.

### Actual Results

With min_resources=30:
```
310	5	960	{'algorithm': 'auto', 'n_neighbors': 15, 'p': 1, 'weights': 'uniform'}	0.804883
311	5	960	{'algorithm': 'brute', 'n_neighbors': 5, 'p': 1, 'weights': 'uniform'}	0.793407
312	5	960	{'algorithm': 'ball_tree', 'n_neighbors': 5, 'p': 1, 'weights': 'uniform'}	0.789650
313	5	960	{'algorithm': 'auto', 'n_neighbors': 5, 'p': 1, 'weights': 'uniform'}	0.789410
314	5	960	{'algorithm': 'kd_tree', 'n_neighbors': 5, 'p': 1, 'weights': 'uniform'}	0.789410
```

### Versions

```shell
System:
    python: 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0]
executable: /usr/bin/python3
   machine: Linux-5.15.109+-x86_64-with-glibc2.35

Python dependencies:
      sklearn: 1.2.2
          pip: 23.1.2
   setuptools: 67.7.2
        numpy: 1.23.5
        scipy: 1.11.2
       Cython: 3.0.2
       pandas: 1.5.3
   matplotlib: 3.7.1
       joblib: 1.3.2
threadpoolctl: 3.2.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 2
         prefix: libopenblas
       filepath: /usr/local/lib/python3.10/dist-packages/numpy.libs/libopenblas64_p-r0-742d56dc.3.20.so
        version: 0.3.20
threading_layer: pthreads
   architecture: Zen

       user_api: openmp
   internal_api: openmp
    num_threads: 2
         prefix: libgomp
       filepath: /usr/local/lib/python3.10/dist-packages/scikit_learn.libs/libgomp-a34b3233.so.1.0.0
        version: None

       user_api: blas
   internal_api: openblas
    num_threads: 2
         prefix: libopenblas
       filepath: /usr/local/lib/python3.10/dist-packages/scipy.libs/libopenblasp-r0-23e5df77.3.21.dev.so
        version: 0.3.21.dev
threading_layer: pthreads
   architecture: Zen

       user_api: blas
   internal_api: openblas
    num_threads: 2
         prefix: libopenblas
       filepath: /usr/local/lib/python3.10/dist-packages/cvxopt.libs/libopenblasp-r0-5c2b7639.3.23.so
        version: 0.3.23
threading_layer: pthreads
   architecture: Zen
```
```

COMMENT:
```py
import numpy as np

rng = np.random.RandomState(0)
n_samples, n_features = 1050, 6
x_train = rng.randn(n_samples, n_features)
y_train = rng.randint(0, 2, n_samples)  # binary target with values in {0, 1}

from sklearn.neighbors import KNeighborsClassifier

knn_grid = dict(n_neighbors=range(5,100,10),
                weights=('uniform', 'distance'),
                algorithm=('auto', 'ball_tree', 'kd_tree', 'brute'),
                p=(1,2)  #When p=1, manhattan_distance, when p=2 euclidean_distance.
)


###How many different combinations?

from sklearn.model_selection import ParameterGrid
param_grid = ParameterGrid(knn_grid)  #a list of dictionaries, one for each combo
len(param_grid)  #160

###How many samples (rows)?

len(x_train)  #1050

from sklearn.experimental import enable_halving_search_cv
from sklearn.model_selection import HalvingGridSearchCV

knn_model = KNeighborsClassifier()

min_res = 30  #change to 'exhaust' for the bug

#do the grid search
halving_cv = HalvingGridSearchCV(
    knn_model, knn_grid,  #our model and the parameter combos we want to try
    scoring="roc_auc",  #from chapter 10
    n_jobs=-1,  #use all available cpus
    min_resources=min_res,
    factor=2,  #double samples and take top half of combos on each iteration
    cv=5, random_state=1234,
    refit=True,  #remembers the best combo and gives us back that model already trained and ready for testing
)

grid_result = halving_cv.fit(x_train, y_train)

import pandas as pd
pd.set_option('display.max_colwidth', None)
df = pd.DataFrame(grid_result.cv_results_)
df[['iter', 'n_resources', 'params', 'mean_test_score']][0:]  #960 with 30, 640 with exhaust (20)
```

Labels: Needs Decision