IPB
ЛогинПароль:

> Прочтите прежде чем задавать вопрос!

1. Заголовок темы должен быть информативным. В противном случае тема удаляется ...
2. Все тексты программ должны помещаться в теги [code=pas] ... [/code], либо быть опубликованы на нашем PasteBin в режиме вечного хранения.
3. Прежде чем задавать вопрос, см. "FAQ", если там не нашли ответа, воспользуйтесь ПОИСКОМ, возможно такую задачу уже решали!
4. Не предлагайте свои решения на других языках, кроме Паскаля (исключение - только с согласия модератора).
5. НЕ используйте форум для личного общения, все что не относится к обсуждению темы - на PM!
6. Одна тема - один вопрос (задача)
7. Проверяйте программы перед тем, как разместить их на форуме!!!
8. Спрашивайте и отвечайте четко и по существу!!!

> Мины, Динамическое программирование
сообщение
Сообщение #1


Бывалый
***

Группа: Пользователи
Сообщений: 152
Пол: Женский

Репутация: -  0  +


Здравствуйте! Нам дали задачу на динамическое программирование толком не обьяснив как можно эту тему использовать в решении задач. Мне дали следующую задачу:
Есть строка, которую вводит пользователь, например: 1 2***3*1 После этого надо написать программу, которая бы сосчитала сколькими способами можно поставить мины, как в игре сапере под каждой цифрой. Как можно подойти к этой задаче? И как рассчитать эти способы? А также массив будет двумерный или одномерный только для самых мин? Спасибо за ответ! И я пользовалась поиском, но по-моему такой темы у вас не была. По крайней мере я ничего не нашла.

Сообщение отредактировано: setare -


--------------------
Ты спрашиваешь, как я переношу длинные бессонные ночи?Как свеча: как только настает утро, я гасну, тем самым, имея возможность заново загореться.

Нима
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов
сообщение
Сообщение #2


Уникум
*******

Группа: Пользователи
Сообщений: 6 823
Пол: Мужской
Реальное имя: Лопáрь (Андрей)

Репутация: -  159  +


setare, я извиняюсь за задержку - перед праздниками очень туго со временем sad.gif. Но если уж пообещал - пришлось сделать smile.gif. Правда, я сомневаюсь, что у тебя еще есть потребность в решении..
Итак, вот программа и небольшие пояснения к ней.
Фактически, вариантом является число, записанное в двоичной форме (1-мина, 0-пусто). Перебор вариантов ведем от 0 до 2^n - 1, где n - разрядность (или число символов в строке), верхние разряды заполняем нулями. В обычном алгоритме честно проверяем каждый вариант. В алгоритме с динамическим программированием (ДП) запоминаем результат проверки варианта и используем его в следующих шагах. Получается быстрее, но нужно много памяти. При длине строки n нужно 2^n байт (точнее - булевских переменных, но в паскале они представляются байтом). Таким образом, при длине строки 30 нужен гигабайт памяти. Программа действительно работает быстрее, но при малой длине строки это мало заметно. Для сравнения я поместил тут оба варианта - с ДП и без ДП (последний - мой, он сильно отличается от того, что предложил Malice). Комментарии самые минимальные. Если нужны подробности - спрашивай.

1. Алгоритм с ДП
uses CRT;
const
Len=29; {Длина строки. Не больше 30}
mx=255;
border=17; {Признак конца данных}

type
tField=array[0..mx]of byte;
tData=array[0..1 shl Len]of boolean;

var
s,m:tField;
si:byte;
n,n1,i,k,left,center,t,v:integer;
c:char;
b,mask:LongInt;
y:boolean;
D:tData;

procedure Inc_m; {Увеличение варианта на единицу}
var
i:integer;
begin
Inc(m[1]);
i:=1;
while m[i]=2 do begin
m[i]:=0;
Inc(i);
Inc(m[i]);
end;
Inc(b);
if i=k then begin
Inc(k); {Запоминаем длину значащей части}
mask:=1 shl (k-2)-1; {Маска выделения предка}
end
end;

procedure WriteArray(s:tField); {Вывод варианта}
begin
for i:=1 to Pred(n) do Write(Char(s[i]+$30)); WriteLn
end;

begin
Write('Input line (1,2,3 or space): ');
n:=1; {Длина введенной строки +1}
v:=0; {Число найденных вариантов}

repeat {Ввод исходной строки}
c:=ReadKey;
case c of
' ','_':begin
s[n]:=0; Write('_'); Inc(n)
end;
'1','2','3':begin
s[n]:=Byte©-$30; Write©; Inc(n)
end;
#8:if n>1 then begin
Write(c,' ',c); Dec(n)
end;
else Write(#7)
end;
until c=#13;
WriteLn;
s[n]:=border;
n1:=Succ(n);
WriteArray(s);

for i:=0 to mx do m[i]:=0;
b:=0; {Вариант, начальное значение}
mask:=0;
D[0]:=true; D[1]:=true;
k:=1; {Начальная длина значащей части варианта +1 }
repeat {Цикл перебора вариантов}
if k<4 then i:=1 else i:=k-3;
left:=m[i-1];
center:=m[i];
if D[b and mask] then begin {Проверяем результат предка}
repeat {Цикл проверки варианта}
t:=left+center;
left:=center;
si:=s[i];
Inc(i);
center:=m[i];
Inc(t,center);
y:=(si=0)or(si=t);
if i=k-2 then {Запоминаем результат проверки предпоследнего разряда}
D[b and mask]:=y
else if i=Pred(k) then
D[b]:=y
until not y;
if i=n1 then begin Inc(v); WriteArray(m) end
end
else D[b]:=false;
Inc_m
until m[n]<>0;
WriteLn('Number of possible combinations: ',v);
ReadLn
end.


2. Алгоритм без ДП
uses CRT;
const
mx=255;
border=17;

type
tData=array[0..mx]of byte;

var
s,m:tData;
si:byte;
n,n1,i,left,center,t,v:integer;
c:char;

procedure Inc_m;
begin
Inc(m[1]);
i:=1;
while m[i]=2 do begin
m[i]:=0;
Inc(i);
Inc(m[i]);
end
end;

procedure WriteArray(s:tData);
begin
for i:=1 to Pred(n) do Write(Char(s[i]+$30)); WriteLn
end;

begin
for i:=0 to mx do m[i]:=0;
Write('Input line (1,2,3 or space): ');
n:=1; {Длина введенной строки + 1}
v:=0; {Число найденных вариантов}
repeat
c:=ReadKey;
case c of
' ','_':begin
s[n]:=0; Write('_'); Inc(n)
end;
'1','2','3':begin
s[n]:=Byte©-$30; Write©; Inc(n)
end;
#8:if n>1 then begin
Write(c,' ',c); Dec(n)
end;
else Write(#7)
end;
until c=#13;
WriteLn;
s[n]:=border;
n1:=Succ(n);
WriteArray(s);

repeat
i:=1;
left:=0;
center:=m[1];
repeat
t:=left+center;
left:=center;
si:=s[i];
Inc(i);
center:=m[i];
Inc(t,center);
until (si<>0)and(si<>t);
if i=n1 then begin Inc(v); WriteArray(m) end;
Inc_m;

until m[n]<>0;
WriteLn('Number of possible combinations: ',v);
end.


--------------------
я - ветер, я северный холодный ветер
я час расставанья, я год возвращенья домой
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

Сообщений в этой теме
setare   Мины   12.12.2005 23:45
klem4   Ты бы поподробне о задаче рассказала ... если уж т…   15.12.2005 0:07
setare   Извините!! Но что вам именно не понятно???…   15.12.2005 0:15
setare   Здравствуйте! Я по подробнее обьяснила условие…   15.12.2005 23:56
setare   Здесь надо составить динамическое пространство, а …   16.12.2005 22:48
lapp   setare, я бы помог (и, думаю, не только я), но вхо…   18.12.2005 17:01
setare   Хорошо!! Просто, понимаете, как сформулиро…   18.12.2005 18:27
lapp   При всем желании никак не могу врубиться: а) зачем…   19.12.2005 15:50
setare   Спасибо, за то, что ты попытался разобраться. Я, к…   19.12.2005 22:19
lapp   setare, в твоем последнем посте наконец-то появила…   20.12.2005 7:59
Atos   Но почему тогда не одна а две строчки с плюсами??   20.12.2005 16:03
lapp   Но почему тогда не одна а [b]две строчки с плюсам…   20.12.2005 16:15
Malice   УУУССССЛЛЛЛОООООВВВВИИИИЕЕЕЕ!!! ну, с…   20.12.2005 18:09
lapp   Мил человек, может ты пояснишь, что есть "сап…   20.12.2005 18:24
Atos   Сапёр, или WinMine - игрушка, входящая в стандартн…   20.12.2005 18:40
Malice   Примерно так: uses crt; var s,s1:string; n,j,i,x:l…   20.12.2005 19:29
setare   Malice, спасибо за программу, но мне кажется, что …   20.12.2005 23:16
Malice   Malice, спасибо за программу, но мне кажется, что…   21.12.2005 3:07
lapp   Сапёр, или WinMine - игрушка, входящая в стандарт…   21.12.2005 11:30
Malice   Она прекрасно работает, но весьма неоптимальна, а…   21.12.2005 13:48
lapp   setare, я извиняюсь за задержку - перед праздникам…   29.12.2005 21:58
setare   Огромное спасибо! Обязательно разберусь в реше…   31.12.2005 18:41


 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 16.06.2024 11:21
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name