Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
 Аватар для Leonman
15 / 15 / 4
Регистрация: 17.06.2012
Сообщений: 274

Рекуррентные соотношения и динамическое программирование

22.07.2016, 06:18. Показов 1767. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую, Форумчане!

Есть задача, которую нужно решить используя динамическое программирование.

Формулировка задачи:
Есть заяц, которому нужно пересечь реку, прыгая по островкам. На каждом островке находится определенное кол-во конфет, которые заяй собирает, попадая на него.
Однако, заяц не может прыгнуть с островка i на островок i+1, заяц может прыгать через один остроков, т.е. c i на i+2 или через два островка, т.е. с i на i+3, как показано на рисунке ниже


Нужно найти максимальное количество конфет, которое может собрать заяц, перебираясь через реку. При этом свой путь, заяц должен заканчивать на n -ом или на n-1 -ом островке, где n - количество островков.

Собственно, решил составить рекуррентные соотношение и пришел вот к чему(конечно оно не верно, иначе яб не писал сейчас все это):
C++
1
a[i] = max(a[i-2], a[i-3]) + candies[i]
где a[i] - макс. количество конфет, которое соберет заяц по пути на i -ый островок, candies[i] - количество конфет, которое дается зайцу на i -ом островке.

И начальные значения(почему именно эти значение, смотреть рисукон выше):
a[0] = 11 (старт зайца)
a[1] = MIN_INT(на первый остовок невозможно попасть)
a[2] = 14 (a[0] + 3)

Кто дошел до конца, вот код, который я написал:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;
#include <string>
using std::string;
#include <fstream>
using std::ifstream;
#include <iterator>
using std::istream_iterator;
#include <sstream>
using std::istringstream;
#include <algorithm>
using std::max;
 
int calcMaxOfCandies(const vector<int> &chain)
{
    vector<int> candies(chain.size(), 0);
    candies[0] = chain[0];
    candies[1] = -32767;
    candies[2] = chain[0] + chain[2];
        
    for(int i = 3; i < candies.size(); i++)
        candies[i] = chain[i] + max(candies[i-2], candies[i-3]);
    
    return candies[candies.size()-1];
}
 
int main()
{
    ifstream fin("data.txt");
    string line;
    std::getline(fin, line);
 
    while(std::getline(fin, line))
    {
        istringstream iss(line);
        vector<int> chain{istream_iterator<int>(iss),
                             istream_iterator<int>()};
        
        cout << calcMaxOfCandies(chain) << " ";
    }
 
    return 0;
}


data.txt(первая строчка, кол-во случаев, вторая и третья, количество конфет на островках)
Кликните здесь для просмотра всего текста
Code
1
2
3
2
11 5 3 17 2 13 19 7
9 7 12 7 16 3 7 17 14 13 4 6 11 6 3 3 5 4 11 3 15 12 14 2 15 19 11 12


Данный код работает верно в ~80% случаях. Я понимаю, почему он не работает. Могу объяснить отдельным комментарием, если понадобится.

Помогите, люди добрые!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
22.07.2016, 06:18
Ответы с готовыми решениями:

Рекуррентные соотношения
Задание во вложениях. нужно его сделать с помощью рекуррентного соотношения(&quot;Элемент последовательности вычисляется на основе...

Рекуррентные соотношения
Помогите написать программу!!!=( Написать программу, вычисляющую первые n элементов заданной последовательности: b1=2, b2=4,...

Рекуррентные соотношения
Последовательность чисел a0, a1, a2, ... образуется по закону: a0=1, a(k) = k*a(k-1)+1/k. (k=1,2... ). Дано натуральное число n. Получить...

19
1617 / 1182 / 553
Регистрация: 08.01.2012
Сообщений: 4,560
22.07.2016, 09:27
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <sstream>
bool jumps(size_t posv,vector<int> v,int *a,int posa,int sum,int&max,int&pmax)
{
    sum+=v[posv];
    if(posv>=v.size()-2)
    {
        if(sum>max)
        {
            pmax=posa;
            a[posa]=v[posv];
            max=sum;
            return true;
        }
        return false;
    }
    bool wasmax=false;
    for(int i=2; i<4; i++)
    if(posv+i<v.size())
        if(jumps(posv+i,v,a,posa+1,sum,max,pmax))
        {
            wasmax=true;
            a[posa]=v[posv];
        }
    return wasmax;
}
void main(int argc,char* argv[])
{
    ifstream fin("data.txt");
    string line;
    std::getline(fin, line);
    int n=atoi(line.c_str());
    for(int i=0; i<n; i++)
    {
        std::getline(fin, line);
        cout<<line<<endl;
        vector<int> v;
        istringstream ss(line);
        string sint;
        while(ss>>sint) v.push_back(atoi(sint.c_str()));
        int *a=new int[v.size()];
        int p,max=0;
        jumps(0,v,a,0,0,max,p);
        for(int i=0; i<=p; i++) cout<<a[i]<<" ";
        cout<<endl;
        delete[] a;
    }
    fin.close();
    system("pause");
}
1
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
22.07.2016, 15:35
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
///////////////////////////////////////////////////////////////////////////////
//1.
///////////////////////////////////////////////////////////////////////////////
//Формулировка задачи:
//Есть заяц, которому нужно пересечь реку, прыгая по островкам. На каждом
//островке находится определенное кол-во конфет, которые заяц собирает,
//попадая на него.
//Однако, заяц не может прыгнуть с островка i на островок i+1, заяц может
//прыгать через один остроков, т.е. c i на i+2 или через два островка, т.е.
//с i на i+3, как показано на рисунке ниже
//Рекуррентные соотношения и динамическое программирование
 
//Нужно найти максимальное количество конфет, которое может собрать заяц,
//перебираясь через реку. При этом свой путь, заяц должен заканчивать
//на n -ом или на n-1 -ом островке, где n - количество островков.
///////////////////////////////////////////////////////////////////////////////
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iterator>
#include <map>
#include <utility>
#include <vector>
///////////////////////////////////////////////////////////////////////////////
typedef std::vector < int   >                           T_islet_values;
typedef T_islet_values::size_type                       T_islet_ind;
typedef int                                             T_jump_ind;
 
typedef std::pair   < T_jump_ind,       T_islet_ind >   T_jump_and_islet_indexes;
typedef std::map    < T_jump_and_islet_indexes, int >   T_res_of_jump_and_islet_indexes;
///////////////////////////////////////////////////////////////////////////////
T_islet_values    get_rand_islet_values( int    islets_total )
{
    const   int     BONBONS_PER_ISLET_MAX   {10};
    T_islet_values  res                     ( islets_total );
 
    std::generate
        (
            res.begin   (),
            res.end     (),
 
            [=]
            {
                return  rand()  %   BONBONS_PER_ISLET_MAX   +   1;
            }
        );
 
    return  res;
}
///////////////////////////////////////////////////////////////////////////////
void    print_islet_values( T_islet_values  const   &   islet_values )
{
    std::copy
        (
            islet_values.begin              (),
            islet_values.end                (),
            std::ostream_iterator< int >    ( std::cout, " " )
        );
 
    std::cout   <<  std::endl;
}
///////////////////////////////////////////////////////////////////////////////
bool    successfully_jump
    (
        T_jump_ind                                      jump_ind,
        T_islet_ind                                     islet_ind_prev,
        int                                             res_prev,
 
        T_islet_values                      const   &   islet_values,
        T_res_of_jump_and_islet_indexes             &   res_of_jump_and_islet_indexes,
        int                                         &   res
    )
{
    const   int     JUMP_DELTA_MIN  {2};
    const   int     JUMP_DELTA_MAX  {3};
    bool            bool_res        {};
 
    for( int  delta = JUMP_DELTA_MIN; delta <= JUMP_DELTA_MAX; ++delta )
    {
        auto        islet_ind   =   islet_ind_prev  +   delta;
 
        if  (
                islet_ind   >=  islet_values.size()
            )
        {
            break;
        }
 
        bool_res                =   true;
 
        auto        new_res     =       res_prev
                                    +   islet_values[ islet_ind ];
 
        auto    &   res_ref     =   res_of_jump_and_islet_indexes
                                        [
                                            std::make_pair
                                                (
                                                    jump_ind,
                                                    islet_ind
                                                )
                                        ];
 
        if  (
                    new_res
                >   res_ref
            )
        {
            res_ref     =   new_res;
        }
    }//for
 
    if  (
                !bool_res
            &&  res_prev    >   res
        )
    {
        res     =   res_prev;
    }
 
    return  bool_res;
}
///////////////////////////////////////////////////////////////////////////////
int     collected_bonbons_max( T_islet_values  const   &   islet_values )
{
    int                                 res{};
    T_res_of_jump_and_islet_indexes     res_of_jump_and_islet_indexes;
    T_jump_ind                          jump_ind_start      {};
    T_islet_ind                         islet_ind_start     {};
 
    res_of_jump_and_islet_indexes
        [
            std::make_pair
                (
                    jump_ind_start++,
                    islet_ind_start
                )
        ]
        =   islet_values[ islet_ind_start ];
 
 
    for ( T_jump_ind  j{ jump_ind_start };; ++j )
    {
        bool    were_jumping{};
 
        for (
                auto
                it  =   res_of_jump_and_islet_indexes.rbegin    ();
                it  !=  res_of_jump_and_islet_indexes.rend      ();
                ++it
            )
        {
            if  (
                    it->first.first     !=  j - 1
                )
            {
                break;
            }
 
            if  (
                    successfully_jump
                        (
                            j,
                            it->first.second,
                            it->second,
 
                            islet_values,
                            res_of_jump_and_islet_indexes,
                            res
                        )
                )
            {
                were_jumping    =   true;
            }
        }//for
 
        if( !were_jumping )
        {
            break;
        }
    }//for
 
    return  res;
}
///////////////////////////////////////////////////////////////////////////////
int     main()
{
    srand(unsigned(time(0)));
 
    for(;;)
    {
        int     islets_total{};
 
        do
        {
            std::cout   <<  "islets total (>0): ";
            std::cin    >>  islets_total;
        }
        while( islets_total     <=  0 );
 
        T_islet_values    islet_values  =   get_rand_islet_values( islets_total );
        print_islet_values( islet_values );
 
        std::cout   <<  "-> "
                    <<  collected_bonbons_max( islet_values )
                    <<  std::endl
                    <<  std::endl;
    }//for
}
1
 Аватар для Leonman
15 / 15 / 4
Регистрация: 17.06.2012
Сообщений: 274
22.07.2016, 16:15  [ТС]
MansMI, Спасибо за ответ. Работает, но хотелось бы без рекурсии.

Добавлено через 4 минуты
Mr.X, Спасибо за ответ. Тоже работает, но конечно с таким количеством typedef`ов... Тяжело становится читать код.

Добавлено через 4 минуты
Если у кого-то есть еще варианты, более простые, выкладывайте. Тема, пока, не закрыта.
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
22.07.2016, 16:30
Цитата Сообщение от Leonman Посмотреть сообщение
Mr.X, Спасибо за ответ. Тоже работает
:D Что значит тоже? У меня именно через динамику сделано, а вот насчет другого решения я не уверен, хотя не вчитывался.
Цитата Сообщение от Leonman Посмотреть сообщение
но конечно с таким количеством typedef`ов... Тяжело становится читать код.
Ну, typedef`ы именно для удобства чтения и придуманы. Или вы хотите сказать, что вместо
T_res_of_jump_and_islet_indexes
удобнее было бы читать что-то вроде
std::map<std::pair<int, size_t>, int>
?
0
 Аватар для Leonman
15 / 15 / 4
Регистрация: 17.06.2012
Сообщений: 274
22.07.2016, 16:33  [ТС]
Mr.X, Ну для меня удобнее былоб читать именно в формате
C++
1
 std::map<std::pair<int, size_t>, int>
. Потому что T_res_of_jump_and_islet_indexes - это понятно именно для вас, как для автора кода, но не для того, кто читает этот код. Чисто ИМХО, не более.
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
22.07.2016, 16:42
Цитата Сообщение от Leonman Посмотреть сообщение
Mr.X, Ну для меня удобнее былоб читать именно в формате
C++
1
std::map<std::pair<int, size_t>, int>
. Потому что T_res_of_jump_and_islet_indexes - это понятно именно для вас, как для автора кода, но не для того, кто читает этот код. Чисто ИМХО, не более.
Только интересно что вы из этого выражения вычитаете? Из моего же названия типа четко видно, что ключом мэпа является пара из индексов прыжка и клетки, а значением - собранные при прыжке в эту клетку конфеты.
0
 Аватар для Leonman
15 / 15 / 4
Регистрация: 17.06.2012
Сообщений: 274
22.07.2016, 19:23  [ТС]
Mr.X, Да, в чем-то вы правы.
Однако из этого T_islet_values не понятно, что это тип vector.
из этого T_jump_and_islet_indexes не понятно, что это тип pair.
из этого T_res_of_jump_and_islet_indexes не понятно, что это тип map<pair<>, int>.
Всю эту информацию приходится держать в голове, когда начинаешь читать код, ну либо постоянно листать и смотреть typedef чего это был.

Вы просто привыкли, потому что, скорее всего, постоянно заменяете подобные типы подобными именами, но для другово человека разобраться в этом не просто.
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
22.07.2016, 19:47
Цитата Сообщение от Leonman Посмотреть сообщение
Однако из этого T_islet_values не понятно, что это тип vector.
из этого T_jump_and_islet_indexes не понятно, что это тип pair.
из этого T_res_of_jump_and_islet_indexes не понятно, что это тип map<pair<>, int>.
Всю эту информацию приходится держать в голове, когда начинаешь читать код, ну либо постоянно листать и смотреть typedef чего это был.
Вы просто привыкли, потому что, скорее всего, постоянно заменяете подобные типы подобными именами, но для другово человека разобраться в этом не просто.
Что-то я не пойму какую альтернативу человеческим названиям типов вы предлагаете. А если голые трехэтажные мэпы писать, то чем это будет понятнее?
Так-то типы отражают предметную область задачи, и читателю кода как раз надо понять как они с ней связаны.
Ну а то, смысл чего ты понял, само запоминается, тем более имена типов говорящие.
В данной задаче ключевой тип - это тип таблицы-мэпа, ну и второй - вектора островков, остальные вспомогательные.
0
 Аватар для Leonman
15 / 15 / 4
Регистрация: 17.06.2012
Сообщений: 274
22.07.2016, 20:06  [ТС]
Mr.X, Ну хотяб как-то так писать: vector_islet_values, pair_jump_and_islet_indexes, map_res_of_jump_and_islet_indexes. Может не так красиво, но во всяком случае понятно, что есть что.

Еще вопрос, с чем связано такое огромное количество пробелом между типами, названиями и т.д.?
Опять же ИМХО, что и это ухудшает читаемость. Весь код растянут, глаза разбегаются.
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
22.07.2016, 20:24
Цитата Сообщение от Leonman Посмотреть сообщение
Mr.X, Ну хотяб как-то так писать: vector_islet_values, pair_jump_and_islet_indexes, map_res_of_jump_and_islet_indexes. Может не так красиво, но во всяком случае понятно, что есть что.
Вообще-то специалисты советуют именовать типы в терминах решаемой задачи, а не языка программирования.
У меня уже как-то выработались правила на этот счет:
- если в названии множественное число, значит контейнер.
- если пара типов через and, значит пара и есть.
- если T_значение_of_ключ, значит мэп.
Цитата Сообщение от Leonman Посмотреть сообщение
Еще вопрос, с чем связано такое огромное количество пробелом между типами, названиями и т.д.?
Опять же ИМХО, что и это ухудшает читаемость. Весь код растянут, глаза разбегаются.
Ну а если код свален в одну строчку, то сначала нужно посчитать скобки и понять где какие, разбить в уме на лексемы, т.е., по сути выполнить парсинг на манер компилятора. А у меня все лексемы на виду, и парсить не надо.
Все именно для удобства.
0
 Аватар для Leonman
15 / 15 / 4
Регистрация: 17.06.2012
Сообщений: 274
22.07.2016, 20:28  [ТС]
Цитата Сообщение от Mr.X Посмотреть сообщение
Вообще-то специалисты советуют
Так это какая-то общепринятая система с typedef`ами и пробелами, которую используют в реально больших и серьезный проектах?
Просто, как правило, такой подход я встречаю именно у матерых ребят.
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
22.07.2016, 20:41
Цитата Сообщение от Leonman Посмотреть сообщение
Просто, как правило, такой подход я встречаю именно у матерых ребят.
Ну, понятие матерости у всех разное. Я вот считаю матерыми авторитетных авторов толковых книг, вот этих, например.
0
 Аватар для Leonman
15 / 15 / 4
Регистрация: 17.06.2012
Сообщений: 274
23.07.2016, 04:23  [ТС]
Mr.X, Кстате говоря, ваш код не правильно работает для значений:
Code
1
9, 7, 12, 7, 16, 3, 7, 17, 14, 13, 4, 6, 11, 6, 3, 3, 5, 4, 11, 3, 15, 12, 14, 2, 15, 19, 11, 12
Правильный ответ 157, ваша программа выдает 100.
1
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
23.07.2016, 10:37
Да, пардон, ошибочка вкралась.
Вот так правильно:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
///////////////////////////////////////////////////////////////////////////////
//2.
///////////////////////////////////////////////////////////////////////////////
//Формулировка задачи:
//Есть заяц, которому нужно пересечь реку, прыгая по островкам. На каждом
//островке находится определенное кол-во конфет, которые заяц собирает,
//попадая на него.
//Однако, заяц не может прыгнуть с островка i на островок i+1, заяц может
//прыгать через один остроков, т.е. c i на i+2 или через два островка, т.е.
//с i на i+3, как показано на рисунке ниже
//Рекуррентные соотношения и динамическое программирование
 
//Нужно найти максимальное количество конфет, которое может собрать заяц,
//перебираясь через реку. При этом свой путь, заяц должен заканчивать
//на n -ом или на n-1 -ом островке, где n - количество островков.
///////////////////////////////////////////////////////////////////////////////
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iterator>
#include <map>
#include <utility>
#include <vector>
///////////////////////////////////////////////////////////////////////////////
typedef std::vector < int   >                           T_islet_values;
typedef T_islet_values::size_type                       T_islet_ind;
typedef int                                             T_jump_ind;
 
typedef std::pair   < T_jump_ind,       T_islet_ind >   T_jump_and_islet_indexes;
typedef std::map    < T_jump_and_islet_indexes, int >   T_res_of_jump_and_islet_indexes;
///////////////////////////////////////////////////////////////////////////////
T_islet_values    get_rand_islet_values( int    islets_total )
{
    const   int     BONBONS_PER_ISLET_MAX   {10};
    T_islet_values  res                     ( islets_total );
 
    std::generate
        (
            res.begin   (),
            res.end     (),
 
            [=]
            {
                return  rand()  %   BONBONS_PER_ISLET_MAX   +   1;
            }
        );
 
    return  res;
}
///////////////////////////////////////////////////////////////////////////////
void    print_islet_values( T_islet_values  const   &   islet_values )
{
    std::copy
        (
            islet_values.begin              (),
            islet_values.end                (),
            std::ostream_iterator< int >    ( std::cout, " " )
        );
 
    std::cout   <<  std::endl;
}
///////////////////////////////////////////////////////////////////////////////
bool    successfully_jump
    (
        T_jump_ind                                      jump_ind,
        T_islet_ind                                     islet_ind_prev,
        int                                             res_prev,
 
        T_islet_values                      const   &   islet_values,
        T_res_of_jump_and_islet_indexes             &   res_of_jump_and_islet_indexes
    )
{
    const   int     JUMP_DELTA_MIN  {2};
    const   int     JUMP_DELTA_MAX  {3};
    bool            bool_res        {};
 
    for( int  delta = JUMP_DELTA_MIN; delta <= JUMP_DELTA_MAX; ++delta )
    {
        auto        islet_ind   =   islet_ind_prev  +   delta;
 
        if  (
                islet_ind   >=  islet_values.size()
            )
        {
            break;
        }
 
        bool_res                =   true;
 
        auto        new_res     =       res_prev
                                    +   islet_values[ islet_ind ];
 
        auto    &   res_ref     =   res_of_jump_and_islet_indexes
                                        [
                                            std::make_pair
                                                (
                                                    jump_ind,
                                                    islet_ind
                                                )
                                        ];
 
        if  (
                    new_res
                >   res_ref
            )
        {
            res_ref     =   new_res;
        }
    }//for
 
    return  bool_res;
}
///////////////////////////////////////////////////////////////////////////////
int     collected_bonbons_max( T_islet_values  const   &   islet_values )
{
    int                                 res{};
    T_res_of_jump_and_islet_indexes     res_of_jump_and_islet_indexes;
    T_jump_ind                          jump_ind_start      {};
    T_islet_ind                         islet_ind_start     {};
 
    res_of_jump_and_islet_indexes
        [
            std::make_pair
                (
                    jump_ind_start,
                    islet_ind_start
                )
        ]
        =   islet_values[ islet_ind_start ];
 
    ++jump_ind_start;
 
    for ( T_jump_ind  j{ jump_ind_start };; ++j )
    {
        bool    were_jumping{};
 
        for (
                auto
                it  =   res_of_jump_and_islet_indexes.lower_bound
                            (
                                std::make_pair( j - 1, 0 )
                            );
 
                it  !=  res_of_jump_and_islet_indexes.end();
                ++it
            )
 
        {
            if  (
                    successfully_jump
                        (
                            j,
                            it->first.second,
                            it->second,
 
                            islet_values,
                            res_of_jump_and_islet_indexes
                        )
                )
            {
                were_jumping    =   true;
            }
            else if( it->second     >   res )
            {
                res     =   it->second;
            }
        }//for
 
        if( !were_jumping )
        {
            break;
        }
    }//for
 
    return  res;
}
///////////////////////////////////////////////////////////////////////////////
int     main()
{
    srand(unsigned(time(0)));
 
    for(;;)
    {
            int     islets_total{};
 
        do
        {
            std::cout   <<  "islets total (>0): ";
            std::cin    >>  islets_total;
        }
        while( islets_total     <=  0 );
 
        T_islet_values    islet_values  =   get_rand_islet_values( islets_total );
        print_islet_values( islet_values );
 
        std::cout   <<  "-> "
                    <<  collected_bonbons_max( islet_values )
                    <<  std::endl
                    <<  std::endl;
    }//for
}
0
 Аватар для Leonman
15 / 15 / 4
Регистрация: 17.06.2012
Сообщений: 274
23.07.2016, 17:02  [ТС]
Mr.X, И еще, в collected_bonbons_max внешний цикл for - лишний.
Если сделать вот так, то все будет также работать, но при этом минус один цикл for и минус несколько ненужных переменных соответственно:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
int     collected_bonbons_max( T_islet_values  const   &   islet_values )
{
    int                                 res{};
    int                                 j{1};
    T_res_of_jump_and_islet_indexes     res_of_jump_and_islet_indexes;
    T_jump_ind                          jump_ind_start      {};
    T_islet_ind                         islet_ind_start     {};
 
    res_of_jump_and_islet_indexes
        [
            std::make_pair
                (
                    jump_ind_start,
                    islet_ind_start
                )
        ]
        =   islet_values[ islet_ind_start ];
        
    for (
            auto
            it  =   res_of_jump_and_islet_indexes.lower_bound
                        (
                            std::make_pair( j - 1, 0 )
                        );
 
            it  !=  res_of_jump_and_islet_indexes.end();
            ++it
        )
 
    {
        if  (
                !successfully_jump
                    (
                        j,
                        it->first.second,
                        it->second,
 
                        islet_values,
                        res_of_jump_and_islet_indexes
                    )
                && it->second     >   res
            )
        {
            res     =   it->second;
        }
    }//for
 
    return  res;
}
1
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
23.07.2016, 19:51
Цитата Сообщение от Leonman Посмотреть сообщение
в collected_bonbons_max внешний цикл for - лишний.
Согласен. От нумерации шагов можно вообще отказаться. Просто идем по таблице и записываем в нее результаты
впереди себя:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
///////////////////////////////////////////////////////////////////////////////
//4.
///////////////////////////////////////////////////////////////////////////////
//Формулировка задачи:
//Есть заяц, которому нужно пересечь реку, прыгая по островкам. На каждом
//островке находится определенное кол-во конфет, которые заяц собирает,
//попадая на него.
//Однако, заяц не может прыгнуть с островка i на островок i+1, заяц может
//прыгать через один остроков, т.е. c i на i+2 или через два островка, т.е.
//с i на i+3, как показано на рисунке ниже
//Рекуррентные соотношения и динамическое программирование
 
//Нужно найти максимальное количество конфет, которое может собрать заяц,
//перебираясь через реку. При этом свой путь, заяц должен заканчивать
//на n -ом или на n-1 -ом островке, где n - количество островков.
///////////////////////////////////////////////////////////////////////////////
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iterator>
#include <map>
#include <vector>
///////////////////////////////////////////////////////////////////////////////
typedef std::vector     < int   >                   T_islet_values;
typedef T_islet_values::size_type                   T_islet_ind;
typedef std::map        < T_islet_ind,  int     >   T_res_of_islet_ind;
///////////////////////////////////////////////////////////////////////////////
T_islet_values    get_rand_islet_values( int    islets_total )
{
    const   int     BONBONS_PER_ISLET_MAX   {10};
    T_islet_values  res                     ( islets_total );
 
    std::generate
        (
            res.begin   (),
            res.end     (),
 
            [=]
            {
                return  rand()  %   BONBONS_PER_ISLET_MAX   +   1;
            }
        );
 
    return  res;
}
///////////////////////////////////////////////////////////////////////////////
void    print_islet_values( T_islet_values  const   &   islet_values )
{
    std::copy
        (
            islet_values.begin              (),
            islet_values.end                (),
            std::ostream_iterator< int >    ( std::cout, " " )
        );
 
    std::cout   <<  std::endl;
}
///////////////////////////////////////////////////////////////////////////////
bool    successfully_jump
    (
        T_islet_ind                     islet_ind_prev,
        int                             res_prev,
 
        T_islet_values      const   &   islet_values,
        T_res_of_islet_ind          &   res_of_islet_ind
    )
{
    static  const   int     JUMP_DELTA_MIN  {2};
    static  const   int     JUMP_DELTA_MAX  {3};
    bool                    bool_res        {};
 
    for( int  delta = JUMP_DELTA_MIN; delta <= JUMP_DELTA_MAX; ++delta )
    {
        auto    islet_ind   =   islet_ind_prev  +   delta;
 
        if  (
                islet_ind   >=  islet_values.size()
            )
        {
            break;
        }
 
        bool_res                =   true;
 
        auto        new_res     =       res_prev
                                    +   islet_values[ islet_ind ];
 
        auto    &   res_ref     =   res_of_islet_ind[ islet_ind ];
 
        if  (
                    new_res
                >   res_ref
            )
        {
            res_ref     =   new_res;
        }
    }//for
 
    return  bool_res;
}
///////////////////////////////////////////////////////////////////////////////
int     collected_bonbons_max( T_islet_values  const   &   islet_values )
{
    int                 res{};
    T_res_of_islet_ind  res_of_islet_ind;
 
    res_of_islet_ind[0]     =   islet_values[0];
 
    for( auto   const   &   islet_ind_and_res   :   res_of_islet_ind )
    {
        auto    res_cur     =   islet_ind_and_res.second;
 
        if  (
                    !successfully_jump
                        (
                            islet_ind_and_res.first,
                            res_cur,
 
                            islet_values,
                            res_of_islet_ind
                        )
 
                &&      res_cur
                    >   res
            )
        {
            res     =   res_cur;
        }
    }//for
 
    return  res;
}///////////////////////////////////////////////////////////////////////////////
int     main()
{
    srand(unsigned(time(0)));
 
    for(;;)
    {
            int     islets_total{};
 
        do
        {
            std::cout   <<  "islets total (>0): ";
            std::cin    >>  islets_total;
        }
        while( islets_total     <=  0 );
 
        T_islet_values    islet_values  =   get_rand_islet_values( islets_total );
        print_islet_values( islet_values );
 
        std::cout   <<  "-> "
                    <<  collected_bonbons_max( islet_values )
                    <<  std::endl
                    <<  std::endl;
    }//for
}
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
23.07.2016, 19:57
Leonman
Что-то не ясно, почему ваш алгоритм не работает.
Если путь зайца лежит через определённую точку K, то он должен достигать этой точки по максимальному пути, иначе общий путь не будет максимальным. Так как прийти в эту точку он может только из двух других: K-2 и K-3, то, зная пути с максимальным весом до этих точек, мы можем найти путь с максимальным весом до K.

Может есть какой-то прозрачный контр-пример?
1
 Аватар для Leonman
15 / 15 / 4
Регистрация: 17.06.2012
Сообщений: 274
24.07.2016, 00:45  [ТС]
mporro, Я почему то думал, что знаю ответ на этот вопрос, но оказалось, что нет и я решил понять, а почему все-таки не работает. И понял

Условие задания гласит, что заяй должен заканчивать на n -ом или n-1 -ом оставке, а я в своей коде совершенно это не учел и return фукнции calcMaxOfCandies() выгледит вот так:
C++
1
return candies[candies.size()-1];
т.е. я все время говорил, что максимальное кол-во конфет окажется, если заяц закончит на n -ом островке, что конечно же не верно в некоторых случаях.

И так как условие задачи разрешает закончить на n -ом или n-1 -ом оставке, изменив
C++
1
return candies[candies.size()-1];
на
C++
1
return candies[candies.size()-1] > candies[candies.size()-2] ? candies[candies.size()-1] : candies[candies.size()-2];
я получил работающий правильно код на любых input`ах.

Спасибо за ваш комментарий, еслиб не он, моя программа так бы и осталась не работающей на любых input`ах.
0
306 / 101 / 18
Регистрация: 04.07.2014
Сообщений: 571
24.07.2016, 05:59
Цитата Сообщение от Leonman Посмотреть сообщение
я получил работающий правильно код
Отлично!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.07.2016, 05:59
Помогаю со студенческими работами здесь

Приближенные вычисления и рекуррентные соотношения
Доброе времени суток, господа и дамы! Помогите пожалуйста разобраться почему код выдает неоднозначность (или что это вообще такое?) ...

Рекуррентные соотношения. Проверка ошибок
Вот готовая программа, но почему она выдаёт всё время для каждого B-нного 0 не понимаю.Помогите найти ошибку #include &lt;iostream&gt; ...

Рекуррентные соотношения. Сумма и произведения
Посмотрел кучу примеров на форуме и не смог понять как из формулы выводить рекурретные соотношения. Где подробно это можно прочитать? ...

Вычисление суммы ряда используя рекуррентные соотношения
Не могу решить задачу №9

Вычисление суммы ряда используя рекуррентные соотношения
Написать программу для вычисления суммы ряда: e^-x=1-x+\frac{x^2}{2!}-\frac{x^3}{3!}+...+(-1)^n*\frac{x^n}{n!}, где n вводится с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru