Логические задачи и головоломки
26 Май 2012, 15:43:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
Новости:
 
   Начало   Правила Помощь Поиск Войти Регистрация Чат  
Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Информатика - программирование (С++)  (Прочитано 762 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
devnull
Старожил
****
Offline Offline

Сообщений: 455


Просмотр профиля
« Ответ #15 : 01 Февраль 2012, 19:16:18 »

Помогите пожалуйста найти ошибку в программе.

В этой программе более одной ошибки. Кроме того, есть места, не являющиеся ошибкой, но сильно некрасивые.
Цитировать
   ifstream fin2("strings.txt");
По условию файл называется string.txt.

Вы изменили мой цикл чтения скобок, добавив в него еще один fin >> c. Видимо, вас к этой мысли привела вот эта часть условия: "В последующих k строках даны через пробел пары символов". Если это так, то вы неправы. Стандартные операторы чтения из потока >> пропускают все начальные пробельные символы (пробелы, табуляции, перевод строки). Иными словами, никакого дополнительного fin>>c в цикле не нужно, иначе вы будете совершенно неправильно читать информацию из файла types.txt.

Цитировать
   string s;
    while (!fin2.eof()){          
        c = fin2.get();
        s.push_back(c);
    }
Некрасивое посимвольное чтение файла, лучше было бы читать его как минимум построчно. В любом случае данный вариант содержит ошибку, которая опасна тем, что может проявиться не всегда. Проблема в том, что флаг конца файла для eof() устанавливается только в результате неуспешной операции чтения из этого файла. В результате получается такое: вы прочитаете последний символ из файла и добавите его к строке. Потом проверите eof(). Поскольку предыдущая операция чтения была успешной, eof() вернет false даже несмотря на то, что мы уже в конце файла. Потом вы пытаетесь прочитать еще один символ из файла. Результат этой операции не определен, в переменной 'c' может оказаться любой мусор. Этот мусор вы добавляете к строке s. И вот только после этого eof() вернет true и вы выйдете из цикла. Так что этот вариант цикла будет всегда дополнять строку одним лишним символом, который будет иметь неопределенное значение. Существуют разные способы избавиться от этой проблемы. Один способ (не очень хороший) - это вынести первое чтение символа перед цикл while, переставив заодно местами операторы внутри цикла:

string s;
c = fin2.get();
while(!fin2.eof()) {
  s.push_back(c);
  c = fin2.get();
}

Но решение в стиле C++ вообще не прибегает к eof():

string s;
while (fin2 >> c) {
  s += c;
}

Пока успешна операция ввода - добавляем символ к строке. Здесь я заодно использовал += вместо push_back, т.к. для типа string это нагляднее. Кроме того, из-за указанного выше свойства оператора >> это решение пропускает при вводе все пробелы. Для контроля скобочной правильности строки это несущественно.

Что касается основного цикла проверки скобочной правильности:
- после того, как вы обработали очередную скобку внутри цикла по i, вы можете использовать оператор break, чтобы сразу перейти к следующей итерации цикла по j;
- когда стек пуст его длина равна нулю а не единице, поэтому проверку if((stack.size()-1)==0) надо заменить на if(stack.size() == 0), а опытные программисты вообще написали бы тут if(stack.empty()).
- вы пишете NO когда стек пуст и это правильно. Но что происходит когда на вершине стека неправильная скобка, т.е. когда проверка if(para(stack[stack.size()-1])==s[j]) не срабатывает? В этом случае тоже должно писаться NO, но у вас этого нет. Доступ к последнему элементу лучше делать через stack.back(). На самом деле эти две проверки должны быть скомбинированы в одну с помощью логического ИЛИ: когда стек пуст ИЛИ на вершине стека плохая скобка:
if(stack.empty() || (para(stack.back()) !=s[j])) { пишем NO } else { вытолкнуть скобку из стека }.
- вместо того, чтобы сравнивать парную скобку для stack.back() с s[j] можно сравнить stack.back() с парной скобкой для s[j]. Но ведь s[j] == ket[i], поэтому парной скобкой для нее будет bra[i] и функция para становится вообще не нужной.

Наконец, после окончания основного цикла вы пишете YES если стек пуст (только опять у вас неправильная проверка на длину стека равную 1), но где вывод NO если стек не пуст? Ваш цикл после минимума исправлений:

    vector<char> stack;
    for(int j = 0; j < s.size(); ++j){
        for(int i = 0; i < k ; i++){
            if(bra[i]==s[j]){
               stack.push_back(s[j]);
               break;  // обработали скобку и переходим к следующему символу строки s
            }
            if(ket[i]==s[j]){
              if(stack.empty() || (stack.back() != bra[i])){
                  cout << "NO";
                  getch();
                  return 0;
              }
              stack.pop_back();
              break;  // обработали скобку и переходим к следующему символу строки s
            }
        }
    }
    if(stack.empty()){
       cout << "YES";
    } else {
       cout << "NO";
    }

« Последнее редактирование: 01 Февраль 2012, 21:17:50 от devnull » Записан
Fylhtq1997
Ветеран
*****
Offline Offline

Сообщений: 533


ЮТШ ЛЭТИ


Просмотр профиля Email
« Ответ #16 : 02 Февраль 2012, 00:14:39 »

Огромное спасибо.  Браво!  Браво!  Браво!
Всё работает.  Ура  Ура  Ура
Спасибо ещё раз, что Вас не затруднило так подробно всё расписать.
Записан

"Лучше понять немного, чем неверно"
"Успех - это умение двигаться от неудачи к неудаче, не теряя оптимизма"
Fylhtq1997
Ветеран
*****
Offline Offline

Сообщений: 533


ЮТШ ЛЭТИ


Просмотр профиля Email
« Ответ #17 : 02 Февраль 2012, 23:28:37 »

Подскажите пожалуйста как работать с классами .
Записан

"Лучше понять немного, чем неверно"
"Успех - это умение двигаться от неудачи к неудаче, не теряя оптимизма"
devnull
Старожил
****
Offline Offline

Сообщений: 455


Просмотр профиля
« Ответ #18 : 03 Февраль 2012, 02:32:55 »

Честно говоря я не знаю, какая литература считается хорошей для изучения С++. Просто задайте в гугл "классы С++" и посмотрите первые несколько ссылок. Что вам покажется понятнее - то и читайте. Можете показать "грязный код", который вам дал преподаватель, тогда будет яснее какой уровень знаний от вас ожидается.
Записан
Fylhtq1997
Ветеран
*****
Offline Offline

Сообщений: 533


ЮТШ ЛЭТИ


Просмотр профиля Email
« Ответ #19 : 08 Февраль 2012, 01:15:19 »

Здравствуйте.
Помогите пожалуйста найти ошибку в 2-ух программах.
Ни как не получается исправить. В первой вообще вылетает.
1)Условие:
Дано прямоугольное поле размером n•m клеток. Козел может совершать прыжки длиной в одну клетку вправо или вверх. Посчитать, сколькими способами козел может попасть из левой нижней клетки в правую верхнюю.
Программа:
#include <iostream>         
#include <fstream>           
#include <conio.h>

using namespace std;

int main(){
    ifstream fin("goat.in.txt");
    int n, m;
    fin >> n;
    fin >> m;
    int f[n - 1][m - 1];
    int i, j;
    for(i = 0 ; i < n ; i++){
          f[ i][0] = 1;
    }
    for(j = 0 ; j < m ; j++){
          f[0][j] = 1;
    }
    for(j = 1 ; j < m ; j++){
          for(i = 1 ; i < n ; i++){
                f[j] = f[i - 1][j] + f[j - 1];
          }
    }
    cout << f[n - 1][m - 1];
    getch();
    return 0;
}

Спасибо.

« Последнее редактирование: 08 Февраль 2012, 01:25:12 от Fylhtq1997 » Записан

"Лучше понять немного, чем неверно"
"Успех - это умение двигаться от неудачи к неудаче, не теряя оптимизма"
Fylhtq1997
Ветеран
*****
Offline Offline

Сообщений: 533


ЮТШ ЛЭТИ


Просмотр профиля Email
« Ответ #20 : 08 Февраль 2012, 01:29:31 »

Я уже сам справился.
Спасибо.
Записан

"Лучше понять немного, чем неверно"
"Успех - это умение двигаться от неудачи к неудаче, не теряя оптимизма"
Fylhtq1997
Ветеран
*****
Offline Offline

Сообщений: 533


ЮТШ ЛЭТИ


Просмотр профиля Email
« Ответ #21 : 17 Февраль 2012, 23:29:05 »

Здравствуйте.
Помогите исправить ошибку пожалуйста.

Дано прямоугольное поле размером n·m клеток. Можно совершать шаги длиной в одну клетку вправо, вверх или по диагонали вправо-вверх. В каждой клетке записано некоторое натуральное число. Необходимо попасть из левой нижней клетки в правую верхнюю. Вес маршрута вычисляется как сумма чисел со всех посещенных клетках. Необходимо найти маршрут с минимальным весом.

Выведите длину наилучшего маршрута и последовательность движений, которые надо совершить, изходя из того, что 'R' – движение вправо, 'U' – движение вверх и 'D' – движение по диагонали вправо-вверх.
             
#include <iostream>         
#include <fstream>         
#include <conio.h>

using namespace std;     
   
int n,m ,i ,j, k;

int min(int b , int c, int p){
    int min;
    if(b<c && b<p){
       min=b;
    }
    if(c<b && c<p){
       min=c;
    }
    if(p<b && p<c){
       min=p;
    }       
    return min;
}

int main(){
    ifstream fin("shortcut.in.txt");
    int n , m ,i ,j , o;
    fin >> n;
    fin >> m;
    int f[n][m], a[n][m];
    string s;
    for(i = m - 1 ;i >= 0 ; i--){
        for( j = 0;j < n; j++){
            fin >> a[ j ][ i ];
        }
    }
   
    f[0][0] = a[0][0];
   
    for(i = 0; i<n; i++){
        for(j = 0 ; j < i ;j++){
            f
  • =a[j][0];
        }
    }   
    for(i = 0; i<n; i++){
        for(j = 0 ; j < i ;j++){
            f[0]=a[0][j];
        }
    }
    for(j = 1; j < m; j++){   
        for(i = 1; i < n; i++){
            f[j]=min(f[i-1][j],f[i-1][j-1],f[j-1])+a[j];
        }
    }
    cout << f[n-1][m-1];
    j = n-2;
    k = m-2;         
    for(i = 0;i<(n + m);i++){
        j--;
        k--;
        if(f[k]=min(f[k],f[i+1][k],f[k+1])){
           s.push_back('D');
           o=i;
        }                                         
        if(f[i+1][k]=min(f[k],f[i+1][k],f[k+1])){
           o=i;
           s.push_back('U');
        } 
        if(f[k+1]=min(f[k],f[i+1][k],f[k+1])){
           o=i;
           s.push_back('R');
        }                                             
    }   
    for(i = o ; i >= 0 ;i--){
        cout << s;
    } 
    getch();
    return 0;
}

Теперь кузнечик может прыгать вперед на разнообразное целое число метров. Вопрос тот же, сколькими способами он способен пропрыгать ровно n метров? В первой строке входного файла содержится m, не превосходящее 100 – число видов прыжков. Затем идут m разных натуральных чисел, каждое из которых не превосходит 1000. Заканчивает файл натуральное число n до 105. Ответ выведите по модулю 109.
#include <iostream>         
#include <fstream>   
#include <conio.h>

using namespace std;       

int n , m ,i ,j;
   
               

int main(){
    ifstream fin("grasshoper.in.txt");
    int n , m ,i ,j;
    fin >> m;
    fin >> n;
    int f[n+1], a[m];
    for(i = 0; i < m; i++){
        fin >> a;
    }
    for(i = 1; i <= n; i++){
        for(j = 0 ; j < m; j++){
            if(i==a[j]){
               f++;   
            }     
            if(i > a[j]){
               f = f + f[i-a[j]];
            }
            else{
                 f=0;
            }           
        }
    }
    cout << f[n];
    getch();
    return 0;
}
               
« Последнее редактирование: 18 Февраль 2012, 13:19:35 от Fylhtq1997 » Записан

"Лучше понять немного, чем неверно"
"Успех - это умение двигаться от неудачи к неудаче, не теряя оптимизма"
Fylhtq1997
Ветеран
*****
Offline Offline

Сообщений: 533


ЮТШ ЛЭТИ


Просмотр профиля Email
« Ответ #22 : 07 Март 2012, 00:43:33 »

Здравствуйте.
С кузнечиком разобрался.
А про путешествие чуть подредактировал.
Не могу только повороты нормально вывести.
Помогите пожалуйста исправить ошибку. Стена
Задача:

Дано прямоугольное поле размером n·m клеток. Можно совершать шаги длиной в одну клетку вправо, вверх или по диагонали вправо-вверх. В каждой клетке записано некоторое натуральное число. Необходимо попасть из левой нижней клетки в правую верхнюю. Вес маршрута вычисляется как сумма чисел со всех посещенных клетках. Необходимо найти маршрут с минимальным весом.

Выведите длину наилучшего маршрута и последовательность движений, которые надо совершить, изходя из того, что 'R' – движение вправо, 'U' – движение вверх и 'D' – движение по диагонали вправо-вверх.

Решение:
Код:

#include <iostream>         
#include <fstream>         
#include <conio.h>

using namespace std;     
   
int n,m ,i ,j, k;

int min(int b , int c, int p){
    int min;
    if(b<c && b<p){
       min=b;
    }
    if(c<b && c<p){
       min=c;
    }
    if(p==b && b==c){
       min=b;
    }     
    if(p<b && p<c){
       min=p;
    }       
    return min;
}

int main(){
    ifstream fin("shortcut.in.txt");
    int n ,z , m ,i ,j , o;
    fin >> n;
    fin >> m;
    int f[n][m], a[n][m];
    string s;
    for(i = m - 1 ;i >= 0 ; i--){
        for( j = 0;j < n; j++){
            fin >> a[ i ][ j ];
        }
    }
   
    f[0][0] = a[0][0];
    f[i][0] = 0;
    f[0][i] = 0;
    for(i = 0; i < n; i++){
        for(j = 0 ; j < i ;j++){
            f[i][0]= f[i][0]+a[j][0];
        }
    }   
    for(i = 0; i < m; i++){
        for(j = 0 ; j < i ;j++){
            f[0][i]= f[0][i]+a[0][j];
        }
    }
    for(j = 1; j < m; j++){   
        for(i = 1; i < n; i++){
            f[i][j]=min(f[i-1][j],f[i-1][j-1],f[i][j-1])+a[i][j];
        }
    }
    cout << f[n-1][m-1];
    j = m-1;
    k = n-1;     
    o = 0;   
    for(i = 0;i<(n + m);i++){
        j--;
        z=0;
        k--;
        if(f[k][j]=min(f[k][j],f[k][j+1],f[k+1][j])){
           s.push_back('D');
           o++;
           z=1;
        }
        if(z==0){                                         
            z++;
            if(f[k][j+1]=min(f[k][j],f[k][j+1],f[k+1][j])){
               if(f[k][j+1]==f[k][j]&& f[k][j]==f[j][k+1]){
                  k--;
                  j--;
               }
               else{
                  o++;
                  s.push_back('U');
               }
            }
        }
        if(z==0){                                         
            z++;
           if(f[k+1][j]=min(f[k][j],f[k][j+1],f[k+1][j])){
               if(f[k][j+1]==f[k][j]&& f[k][j]==f[j][k+1]){
                  k--;
                  j--;
               }
               else{
                   o++;
                   s.push_back('R');
               }
            }
        }                                             
    }   
    for(i = o ; i >=0 ;i--){
        cout << s[ i ];
    } 
    getch();
    return 0;
}
Зарание спасибо.
« Последнее редактирование: 07 Март 2012, 01:07:15 от Fylhtq1997 » Записан

"Лучше понять немного, чем неверно"
"Успех - это умение двигаться от неудачи к неудаче, не теряя оптимизма"
devnull
Старожил
****
Offline Offline

Сообщений: 455


Просмотр профиля
« Ответ #23 : 07 Март 2012, 00:58:26 »

Пожалуйста, заключите свой код в тэги [code] и [/code], иначе индекс [i] превращает программу в нечитаемое месиво. Другой способ, который я использовал для вставки [i] в это сообщение - это писать [[i][/i]i], т.е. сразу после открывающей квадратной скобки включать и сразу выключать курсив. Но в длинной программе это может быть слишком трудоемко, если делать такие подстановки вручную. Ставить пробелы [ i ] тоже можно, но не менее трудоемко.
« Последнее редактирование: 07 Март 2012, 01:02:27 от devnull » Записан
Fylhtq1997
Ветеран
*****
Offline Offline

Сообщений: 533


ЮТШ ЛЭТИ


Просмотр профиля Email
« Ответ #24 : 07 Март 2012, 01:07:48 »

Пожалуйста, заключите свой код в тэги [code] и [/code], иначе индекс [i] превращает программу в нечитаемое месиво. Другой способ, который я использовал для вставки [i] в это сообщение - это писать [[i][/i]i], т.е. сразу после открывающей квадратной скобки включать и сразу выключать курсив. Но в длинной программе это может быть слишком трудоемко, если делать такие подстановки вручную. Ставить пробелы [ i ] тоже можно, но не менее трудоемко.
Сделал помолго спасибо буду знать.
Записан

"Лучше понять немного, чем неверно"
"Успех - это умение двигаться от неудачи к неудаче, не теряя оптимизма"
devnull
Старожил
****
Offline Offline

Сообщений: 455


Просмотр профиля
« Ответ #25 : 07 Март 2012, 18:48:02 »

Смотрите личные сообщения.
Записан
Fylhtq1997
Ветеран
*****
Offline Offline

Сообщений: 533


ЮТШ ЛЭТИ


Просмотр профиля Email
« Ответ #26 : 17 Март 2012, 01:31:57 »

Здравствуйте.
Мне задали написать алгоритм Робина карпа.
Я почитал в интернете про этот алгоритм не моглибы вы мне пояснить его прелести и почему в 4 строке "s[i+j-1]"
1 function NaiveSearch(string s[1..n], string sub[1..m])
2     for i from 1 to n
3         for j from 1 to m
4             if s[i+j-1] ≠ sub[j]
5                 jump to next iteration of outer loop
6         return i
7     return not found
Спасибо.
Записан

"Лучше понять немного, чем неверно"
"Успех - это умение двигаться от неудачи к неудаче, не теряя оптимизма"
Fylhtq1997
Ветеран
*****
Offline Offline

Сообщений: 533


ЮТШ ЛЭТИ


Просмотр профиля Email
« Ответ #27 : 17 Март 2012, 03:40:11 »

Помогите пожалуйста исправить ошибку в задаче.
1) требуется чтобы программа искала в строке под строку за N*M где N-длина строки M- длина построки
решение:
#include <stdio.h>
#include <iostream>         
#include <fstream>         
#include <conio.h>

using namespace std;

int main(){
    ifstream fin("pip.in.txt");
    int i , j , m , n ;
    fin >> n;   
    string t;
    fin >> m;
    string p;
    for(i = 0 ; i < n ; i++){
        fin >> t;
        }
   
    for(j = 0 ; j < m ; j++){
        fin >> p[j];
    }
    int o , z;
    z = 0;
    for(i = 0 ; i < n - m + 1 ; i++){
        for(j = 0 ; j < m ; j++){
            if(z==m){
               cout << o ;
               getch();     
               return 0;
            }
            else{     
                if(p[j] = t){
                    z++;
                    if(z == 0){
                        o = i;
                    }
                }
                else{
                     z = 0;
                }
            }
        }
    }
    getch();
    return 0;                     
}   

2)требуется исбользовать алгоритм Робина Карпа => будет работать быстрее.
решение:
 
#include <stdio.h>
#include <iostream>         
#include <fstream>         
#include <conio.h>

using namespace std;

int main(){
    ifstream fin("pip.in.txt");
    int i , j , m , n ;
    fin >> n;   
    string t;
    fin >> m;
    string p;
    for(i = 0 ; i < n ; i++){
        fin >> t;
    }
     for(j = 0 ; j < m ; j++){
        fin >> p[j];
    }
   
    for(i = 0;i < n-m; i++){
        for(j = 0; j < m; j++){
            if(t[i+j-1]!=p[j]){
               j++;
            }
            cout << i;
        }
    }
    getch();
    return 0;
}
                                         
Спасибо.
Записан

"Лучше понять немного, чем неверно"
"Успех - это умение двигаться от неудачи к неудаче, не теряя оптимизма"
Fylhtq1997
Ветеран
*****
Offline Offline

Сообщений: 533


ЮТШ ЛЭТИ


Просмотр профиля Email
« Ответ #28 : 24 Март 2012, 01:43:35 »

Здравствуйте.
Как закрыть тему эту?
Тут всё равно не помогают.
Записан

"Лучше понять немного, чем неверно"
"Успех - это умение двигаться от неудачи к неудаче, не теряя оптимизма"
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  

Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC | Sitemap