2015-04-27 6 views
1

Я пытаюсь научить себя C++, и я наткнулся на эту программу проекта в моей книге я работаю с:поклонника устранение

В древней земле, прекрасная принцесса Евы было много поклонников. Она решила следующую процедуру, чтобы определить, кто жених женится. Во-первых, все женихи будут выстраиваться один за другим и назначать номера.

Первым женихом будет номер 1, второе число 2 и т. Д. До последнего жениха, номер n. Начиная с первого жениха, она посчитала бы три жениха вниз по линии (из-за трех букв на ее имя), и третий жених был бы исключен из победы над своей рукой и удалился с линии. Ева продолжала бы, считая еще три жениха и устраняя каждого третьего жениха. Когда она дошла до конца линии, она продолжала считать с самого начала.

Например, если было шесть женихов тогда процесс ликвидации будет действовать следующим образом:

123456 первоначальный список женихов, начать отсчет с 1

12456 ухажера 3 устранен, продолжает отсчет от 4

1 245 ухажер 6 устранены, по-прежнему считая от 1

125 ухажера 4 устранено, продолжает отсчет от 5

15 ухажера 2 устранено, по-прежнему считая от 5

1 жениха 5 устранен, 1 является счастливым обладателем

Написать программу, которая использует вектор для определения, какое положение вы должны стоять, чтобы жениться на принцессе, если являются n женихами. Вы можете использовать следующую функцию из класса Vector:

v.erase (iter);

// Удаляет элемент в позиции ITER

Например, чтобы использовать эту функцию, чтобы удалить четвертый элемент с начала векторной переменной с именем theVector, использовать

theVector.erase (theVector.begin () + 3);

Номер 3 используется потому, что первый элемент в векторе находится в позиции с индексом 0.

Я написал некоторые предварительные код, но я с трудом выяснить, как сказать программе после первого suitor (т. е. третий жених) исключается, чтобы начать отсчет с четвертого жениха и т. д. Возможно, вложенная петля будет работать? Я нашел решения в Интернете, которые используют класс, но мне трудно понять, и я чувствую, что есть более простой способ решения этой проблемы, любая помощь будет очень признательна.

#include <iostream> 
#include <vector> 

using namespace std; 

int main() 
{ 
int n; 
vector<int> vec; 
cout << "Enter the number of suitors: " << endl; 
cin >> n; 

// set some values (from 1 to n) 
for(int i = 0; i <= n; i++){ 
    vec.push_back(i); 
} 
// erase third suitor 
    vec.erase(vec.begin()+2); 

// print vector with erased suitor 
    for(unsigned i = 0; i <= vec.size(); i++){ 
    cout << vec[i] << endl; 
    } 


} 
+0

Думайте, «как далеко отсюда следующий». Если вы удалили кандидата с индексом 'x', следующий кандидат теперь находится в' x + 2' ('x + 3 - 1', он переместил один« шаг »). Чтобы безопасно «обернуть» вектор, читайте о модуле '%'. Вероятно, это обсуждается в той же главе, что и упражнение. – molbdnilo

ответ

2

Прежде всего, есть две ошибки в вашей программе: вы сначала положить [0, n] в векторе, который должен быть [1, n], и при печати содержимого вектора, можно использовать <=, где она должна быть <.

Теперь для актуального вопроса.Мы хотим, чтобы перебрать вектор с шагом размера 2 (второй человек справа от текущего пользователя):

for (int i = 0; i < vec.size(); i += 2) 

Однако, когда мы достигаем конца массива, мы хотим, чтобы продолжить отсчет от фронт. Для этого мы можем использовать оператор по модулю %:

for (int i = 0; i < vec.size(); i = (i + 2) % vec.size()) 

Это ограничит i в диапазоне [0, vec.size() - 1]. Таким образом, наше условие цикла теперь бесполезно. Вместо этого, мы должны позаботиться, чтобы завершить цикл, когда размер вектора является 1:

for (int i = 0; vec.size() > 1; i = (i + 2) % vec.size()) 

Собираем вместе, мы получим следующее:

for (int i = 0; vec.size() > 1; i = (i + 2) % vec.size()) 
    vec.erase(vec.begin() + i + 2); 

Или что то же самое:

for (int i = 2; vec.size() > 1; i = (i + 2) % vec.size()) 
    vec.erase(vec.begin() + i); 

Единственный элемент, который находится в векторе, когда этот цикл завершается, - это число счастливчиков.

EDIT: Для того, чтобы распечатать содержимое вектора после каждого исключения, попробуйте следующее:

for (int i = 2; vec.size() > 1; i = (i + 2) % vec.size()) 
{ 
    vec.erase(vec.begin() + i); 

    for (int j = 0; j < vec.size(); j++) 
     cout << vec[j]; 
    cout << endl; 
} 
+0

Я думаю, что понимаю, что цикл for вы сделали, мой единственный (глупый) вопрос - как вы распечатываете вектор? –

+0

@MorganWeiss Я обновил свой ответ. –

+0

Я думаю, вы имеете в виду vec [j] not v [j], правильно? –

0

Относительного позиционирование и воспользоваться vec.erase() 's возвращаемого значения.

newpos = vec.erase(pos); 

Здесь 'newpos' указывает на элемент, который следует за стираемым. Смысл уши «3» от {1, 2, 3, 4, 5, 6} позволяет указать на «4». Затем вы можете сделать

pos = vec.begin(); 
while (pos != vec.end()) { 
    erasePos = // compute erasing position relative to 'pos' 
       // e.g. pos + 2, within bounds 
    pos = vec.erase(erasePos); 
} 

Вам необходимо сделать это в цикле.

0

Для этого случая использования, когда вы просто повторяете до конца и возвращаете назад к началу, я бы использовал list вместо vector. Программа может быть:

#include <iostream> 
#include <list> 

using namespace std; 

int main() { 
    list<int> l; 
    int n; 
    int i; 
    cout << "Enter the number of suitors: "; 
    cin >> n; 

    for (i=0; i<n; i++) l.push_back(i); 

    int delta = 3; // want to remove every third 
    i = delta; 
    list<int>::iterator it = l.begin(); 
    while (l.size() > 1) { // loop until only one left 
     if (--i == 0) { // is it third ? 
      list<int>::iterator it2 = it++; // move pointer one step further (erase would destroy it) 
      l.erase(it2); // remove it 
      i = delta; // rearm counter 
     } 
     else it++; // was not third, simply goes on 

     if (it == l.end()) it = l.begin(); // if at end, go back to begin 
    } 
    cout << "Winner is number : " << l.front() + 1 << endl; // add one as our list was 0,1,...n-1 
    return 0; 
} 
Смежные вопросы