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

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

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

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


Бывалый
***

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

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


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

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


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

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


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

 



- Текстовая версия 20.06.2025 23:38
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"