Estou tentando usar programação dinâmica para resolver uma variação de mochila, onde você recebe uma série de recipientes, cada um deles tendo um peso, uma resistência e um id. Preciso encontrar a pilha mais alta deles com as seguintes restrições:
- Um contêiner não pode ser colocado acima de outro com um ID maior.
- A soma total do peso de todos os contêineres acima de outro não pode superar sua resistência. Por exemplo: Tendo os seguintes contêineres (Container(id,weight,resistance)) {Container(1,3,3), Container(2,10,2), Container(3,10,2), Container(4,1,2), Container(5,2,12)} A solução seria (de cima para baixo) 5,4,1. Nota: Se houver mais de uma solução, o programa pode dar qualquer uma delas, desde que estejam corretas. Os contêineres vêm ordenados por id.
Já resolvi o problema com uma função recursiva e memorização, porém não consigo descobrir como gerenciar corretamente as resistências e suas variações com o peso dos recipientes.
Acredito que foi o mais longe que cheguei:
public static List<Container> findBestPile(List<Container> containers){
int n = containers.size();
int[] dp = new int[n];
int[] previous = new int[n];
int[] resistance = new int[n];
Arrays.fill(dp, 1);
Arrays.fill(previous, -1);
for(int i = 0; i < n; i++) resistance[i] = containers.get(i).resistance;
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
// Verify if object i can be after object j
if (containers.get(i).weight <= resistance[j] && dp[j] + 1 > dp[i]) {
dp[i] = dp[j] + 1;
previous[i] = j;
resistance[i] = Math.min(resistance[j] - containers.get(i).weight, containers.get(i).resistance);
}
}
}
// Find biggest index in dp
int maxIndex = 0;
for (int i = 1; i < n; i++) {
if (dp[i] > dp[maxIndex]) {
maxIndex = i;
}
}
// Reconstruct the biggest pile from the "previous" array
List<Container> bestPile = new ArrayList<>();
for (int i = maxIndex; i != -1; i = previous[i]) {
bestPile.add(containers.get(i));
}
return bestPile;
}