Помогите решить олимпиадную задачу по информатике

77
01 ноября 2021, 05:50

Условие : Дано массив чисел. За один ход разрешается вычеркнуть любую последовательность одинаковых цифр, идущих подряд . Сколько минимально ходов нужно, чтобы зачеркнуть все элементы массива ? Длина массива не больше 200.

Пример :

Пусть  задан такой массив - [1 , 2 , 3 , 2 , 1 , 3 ,3];
1) [1,2,3,2,1];
2) [1,2,2,1];
3) [1,1];
4) []
Ответ : 4 ; 

Мой код(простите за плохой код, я только начинаю заниматься программированием) :

#include <bits/stdc++.h>
using namespace std;
vector < int > DeleteSubArray(int l , int r , vector < int > vec){
        vec.erase(vec.begin() + l , vec.begin() + r);
        return vec;
}
int Operations (vector < int > v) {
    if(v.size() == 0)
        return 0 ;
    int ans  = INT_MAX , left = 0;
    for(int i = 1 ; i < v.size() ; i++)
            if(v[i]!= v[i - 1]){
                ans = min(ans  , Operations(DeleteSubArray(left , i , v)) + 1 );
                left = i;
            }
    ans = min(ans , Operations(DeleteSubArray(left , v.size() , v)) + 1 );
    return ans ;
}
int main()
{
    vector < int > v = {1 , 2 , 3 , 2 , 1 , 3 , 3} ;
    cout << Operations(v);
    return 0;
}

Помогите придумать более эффективный алгоритм, перебор рекурсией не проходит по времени (1 секунда)

Answer 1

Идея достаточно простая. Ограничение всего 200, поэтому ничего сложного можно не писать (а можно и значительно оптимальнее решить эту задачу).

Всего у нас не более 200*200/2 = 20к отрезков. Если мы в каждом отрезке просто переберём что мы убираем. То это не большее 200 операций. База динамики - единичные отрезки уходят за 1 операцию.

Или более формально.

F[i][i] = 0
F[i][i+1] = 1
F[i][j] = min( F[i][k-1] + F[k_next][j] + 1) по всем k от i до j. 
          k_next - первый элемент больше k не совпадающий с ним. 

Естественно, вычислять надо от меньшей длины к больше. Примерный код

for (int d = 2; d < N; d++)
   for (int i=0; i < N-d; i++)
        recalc (i, i+d);

Ответ - значение F[0][N-1].

Полный код не пишу, т.к. считаю что олимпиады самому решать надо.

Сложность - O(N^2) память и O(N^3) время.

READ ALSO
Наследование значений С++

Наследование значений С++

Я не совсем понимаю как работает наследование

70
c++ algorithm что то пошло не так

c++ algorithm что то пошло не так

написал вроде все правильно, но не работает

105
Как в Web Socket передать сообщение с custom name

Как в Web Socket передать сообщение с custom name

Подскажите пожалуйстаУ меня есть серверная и клиентская часть написанная на Web Socket

124
Render inside foreach

Render inside foreach

Изучаю JS + RN и пишу приложение с навигациейХочу отрендерить компонент в зависимости от переданных в него пропсов

78