Консультация № 181931
18.01.2011, 18:10
55.00 руб.
0 39 4
Добрый день, уважаемые эксперты!

Представим, что есть поле размером 5 на 5 клеток. На этом поле нужно разместить три фигурки - две двухклеточных и одну одноклеточную, размещать фигурки нужно так, чтобы они друг друга не касались (ни сторонами, ни уголками), четко по клеткам.

Задача такая: нужно перебрать все возможные варианты размещения фигурок и составить три таблички:

1) табличка 5*5, соответствующая исходному полю, в каждой ячейке нужно указать количество вариантов, при которых в клетке поля, соответствующей данной ячейке таблицы, будет находится клетка двухклеточной фигурки (любой из двух);

2) табличка 5*5, соответствующая исходному полю, в каждой ячейке нужно указать количество вариантов, при которых в клетке поля, соответствующей данной ячейке таблицы, будет находится клетка одноклеточной фигурки;

3) табличка 5*5, соответствующая исходному полю, в каждой ячейке нужно указать количество вариантов, при которых в клетке поля, соответствующей данной ячейке таблицы, будет находится клетка фигурки (любой из трех).

В ответе кроме этих табличек еще хотелось бы видеть:

а) общее количество вариантов размещения;

б) метод решения задачи;

в) сколько времени ушло на решение - на составление алгоритма, сколько времени программа выполнялась (если будет использоваться программа) и т.п.

Решать можно как угодно, приветствуются самые разные варианты!

Если что-то непонятно в условии - отвечу в мини-форуме.

Спасибо!

Обсуждение

Неизвестный
19.01.2011, 16:09
общий
Адресаты:
Сейчас попробую такой же список составить
давно
Старший Модератор
31795
6196
19.01.2011, 16:13
общий
Адресаты:
У меня не считаются комбинации, когда 2-х палубники повернуты влево и вверх, т.к. такое положение уже считалось, когда они были повернуты вправо и вниз. Отсюда и расхождения по 2-х палубникам.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
19.01.2011, 16:15
общий
Вообще лучше отлаживать на более простом примере, который можно просчитать вручную (это в свою очередь требует определённой "масштабируемости" от программы).
Например, поле 3х3 с одним 2-двухклеточным и одним одноклеточным. Моя программа выдаёт такой результат:
Код:

Field: 3x3
Items: { 2 1 }
...
Total: 24
Length 1 table:
4 2 4
2 0 2
4 2 4
Length 2 table:
6 6 6
6 0 6
6 6 6
Неизвестный
19.01.2011, 16:19
общий
Кстати да, для двухпалубников считаем обе клетки равнозначными, так что перевертыши - это один вариант.
Неизвестный
19.01.2011, 16:19
общий
Адресаты:
Вы свой ответ потом оформить тоже не забудьте. ;)
давно
Посетитель
7438
7205
19.01.2011, 16:23
общий
Адресаты:
Так у меня тоже :)
Сейчас я сверяю результаты - пока все сходится...
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Старший Модератор
31795
6196
19.01.2011, 16:26
общий
Цитата: 321399
Вообще лучше отлаживать на более простом примере, который можно просчитать вручную

Код:
220
000
220

220
000
022

202
202
000

200
202
002

022
000
220

022
000
022

002
202
200

000
202
202

Проверьте, куда можно одну лишнюю клеточку впихнуть.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Посетитель
7438
7205
19.01.2011, 16:30
общий
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Старший Модератор
31795
6196
19.01.2011, 16:40
общий
Упс тупанул я.
[code h=100]220
000
111

201
201
001

022
000
111

020
020
000

102
102
100

000
220
000

001
201
201

000
022
000

000
020
020

100
102
102

111
000
220

111
000
022

6 6 6
6 0 6
6 6 6


4 2 4
2 0 2
4 2 4
[/code]
только потом заметил
Цитата: 321399
одним 2-двухклеточным и одним одноклеточным.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
19.01.2011, 16:42
общий
Адресаты:
Если убрать лишний двухпалубник, то места достаточно
давно
Посетитель
7438
7205
19.01.2011, 16:43
общий
Адресаты:
Следом и я
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
19.01.2011, 16:44
общий
Адресаты:
Мой список оказался подозрительно ровно в два раза длиннее
Неизвестный
19.01.2011, 16:46
общий
Адресаты:
Нашёл у себя ошибку, у меня все фигурки считаются различимыми. Поэтому мои таблички надо делить на 2!
Неизвестный
19.01.2011, 17:16
общий
Выложил исправленный вариант
давно
Посетитель
7438
7205
19.01.2011, 17:30
общий
Ха, я у себя тоже нашел ошибку: два раза складывал. (видать, скопировал лишний раз, так и осталось)
Так что теперь результаты единтичны!
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
19.01.2011, 17:39
общий
Адресаты:
Выкладывайте свою программу. Вы единственный, кто сразу дал правильный результат.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
19.01.2011, 18:09
общий
Молодцы :)
Неизвестный
19.01.2011, 19:30
общий
Адресаты:
лучше сделать, серым-курсивом. Красное это модераторское.
Как скажете
Неизвестный
19.01.2011, 19:35
общий
Так что теперь результаты единтичны!

Да, теперь можно считать, что добрались до истины
Неизвестный
19.01.2011, 20:05
общий
Можно полюбопытствовать почему в задаче используется поле 5х5?
Для решения на бумаге это много, получится слишком долго и нудно. Для машинного поиска - слишком мало, даже самый бесхитростный алгоритм найдёт решение за несколько секунд.
давно
Старший Модератор
31795
6196
19.01.2011, 20:07
общий
это ответ
Здравствуйте, lupus campestris!
Смотрите приложение. В отличии от программы в мини-форуме, добавлено определение времени и удален служебный код.
Результат работы программы:
Двойные:
[table][row][col]608[/col][col]718[/col][col]622[/col][col]718[/col][col]608[/col][/row][row][col]718[/col][col]608[/col][col]508[/col][col]608[/col][col]718[/col][/row][row][col]622[/col][col]508[/col][col]424[/col][col]508[/col][col]622[/col][/row][row][col]718[/col][col]608[/col][col]508[/col][col]608[/col][col]718[/col][/row][row][col]608[/col][col]718[/col][col]622[/col][col]718[/col][col]608[/col][/row][/table]
Одиночные:
[table][row][col]242[/col][col]179[/col][col]151[/col][col]179[/col][col]242[/col][/row][row][col]179[/col][col]111[/col][col]89[/col][col]111[/col][col]179[/col][/row][row][col]151[/col][col]89[/col][col]84[/col][col]89[/col][col]151[/col][/row][row][col]179[/col][col]111[/col][col]89[/col][col]111[/col][col]179[/col][/row][row][col]242[/col][col]179[/col][col]151[/col][col]179[/col][col]242[/col][/row][/table]
Суммарные:
[table][row][col]850[/col][col]897[/col][col]773[/col][col]897[/col][col]850[/col][/row][row][col]897[/col][col]719[/col][col]597[/col][col]719[/col][col]897[/col][/row][row][col]773[/col][col]597[/col][col]508[/col][col]597[/col][col]773[/col][/row][row][col]897[/col][col]719[/col][col]597[/col][col]719[/col][col]897[/col][/row][row][col]850[/col][col]897[/col][col]773[/col][col]897[/col][col]850[/col][/row][/table]
Total: 3888
Time: 0

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

в) Время написания- 2-а часа с перерывами, время работы - 0(Как не старался получить время, результат - ноль.возможно на старых машинах его можно будет определить).

Удачи!

Приложение:
uses crt,dos;
const
n=5;
type
tmass=array[1..n,1..n]of integer;
var
a,b,c:tmass;
d:text;
x1,y1,x2,y2,e,f,i,j,h,l:integer;
b1,b2,b3,b4,e1,e2,e3,e4:word;
p:^longint;
function K(kk:integer):boolean;
begin
K:=(kk>0)and(kk<=n);
end;
procedure G(x,y:integer);
begin
for i:=-1 to 1 do
for j:=-1 to 1 do
if K(x+i)and K(y+j)then a[x+i,y+j]:=0;
end;
procedure Z(var zz:tmass;zzz:integer);
begin
for i:=1 to n do
for j:=1 to n do
zz[i,j]:=zzz;
end;
begin
Z(b,0);
Z(c,0);
assign(d,'l.txt');
rewrite(d);
l:=0;
Gettime(b1,b2,b3,b4);
for x1:=1 to n do
for y1:=1 to n do
begin
e:=2;
repeat
dec(e);
for x2:=x1 to n do
begin
if x2=x1 then y2:=y1+1
else y2:=1;
while y2<=n do
begin
f:=2;
repeat
dec(f);
if K(x1+1-e)and K(y1+e)and
K(x2+1-f)and K(y2+f)then
begin
Z(a,2);
G(x1,y1);
G(x1+1-e,y1+e);
if(a[x2,y2]<>0)and(a[x2+1-f,y2+f]<>0)
then
begin
G(x2,y2);
G(x2+1-f,y2+f);
h:=0;
for i:=1 to n do
for j:=1 to n do
begin
h:=h+(a[i,j] div 2);
c[i,j]:=c[i,j] + (a[i,j] div 2);
end;
b[x1,y1]:=b[x1,y1]+h;
b[x1+1-e,y1+e]:=b[x1+1-e,y1+e]+h;
b[x2,y2]:=b[x2,y2]+h;
b[x2+1-f,y2+f]:=b[x2+1-f,y2+f]+h;
l:=l+h;
end;
end;
until f=0;
inc(y2);
end;
end;
until e=0;
end;
GetTime(e1,e2,e3,e4);
for i:=1 to n do
begin
for j:=1 to n do
write(d,b[i,j]:7);
writeln(d);
end;
writeln(d);
writeln(d);
for i:=1 to n do
begin
for j:=1 to n do
write(d,c[i,j]:7);
writeln(d);
end;
writeln(d);
writeln(d);
for i:=1 to n do
begin
for j:=1 to n do
write(d,(c[i,j]+b[i,j]):7);
writeln(d);
end;
writeln(d);
writeln(d,'Total:',l:7);
writeln(d,'Time:',(e4-b4+100*(e3-b3+60*(e2-b2+60*(e1-b1)))):7);
close(d);
writeln;
readln;
end.
5
Спасибо за ответ! :)
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
19.01.2011, 20:23
общий
Цитата: 321399
Для машинного поиска - слишком мало, даже самый бесхитростный алгоритм найдёт решение за несколько секунд.

При желании алгоритм можно ускорить, сократив до перебора вариантов:
[table][row][col red] [/col][col] [/col][/row][row][col] [/col][col red] [/col][/row][/table]
и
[table][row][col red] [/col][col] [/col][/row][row][col red] [/col][col] [/col][/row][/table]
А точные значения получить, если учесть повороты и перевороты вокруг осей и диогоналей.
т.е. ещё меньше времени.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
19.01.2011, 20:24
общий
Хороший вопрос. :)
История вопроса такая - задумалась о том, чтобы сделать игру "Морской бой". Подумала, что несколько уровней было бы неплохо. Есть обычный морской бой, в который мы все играли, и есть еще версия с красным крестом, посложнее. Но два уровня маловато во-первых, а во-вторых, все равно надо думать о том, как лучше делать ходы. Слишком легко - неинтересно будет, слишком сложно - играть никто не будет.
Поэтому возникла идея с четырьмя уровнями, с постепенной возможностью перехода. То есть набрал какое-то количество очков на самом простом уровне - можешь переходить на следующий.
Уровни такие:
1) обычная игра, делать ходы наугад, но по правилам (то есть просто не бить в клетку, соседнюю с "ранен/убит", возможно, добивать корабли после ранения)
2) обычная игра, делать ходы с соблюдением четности (пока есть корабли не только одноклеточные - ходить только по клеткам одного цвета как в шахматной доске, так больше шансов быстрее отловить большие корабли, а одноклеточные уже искать наугад)
3) обычная игра, но делать ходы с учетом вероятностей
4) игра с красными крестами, это пока оставим.
Вот по пункту 3 и появился вопрос - а есть ли она эта вероятность, ну разве что кроме бортов поля? Если есть, то можно после каждого полученного ответа пересчитывать варианты и запрашивать опять клетки с наилучшими шансами. Причем было бы интересно отслеживать шансы даже не по суммарным значениям, а по конкретным типам кораблей.
Но это все имеет смысл, если действительно есть эти неравномерности.
Для стандартного поля считать может быть и много, а главное бессмысленно, если это напрасно. Поэтому сначала решила проверить на небольшом поле с примерно соответствующими условиями.
Мне и самой посчитать не лень, но это надо ждать следующих выходных, а может и тогда времени не будет. А так интересно было узнать, как думают эксперты.И будут ли какие-то интересные алгоритмические находки. :)
Похоже, что смысл возиться с большим полем все-таки есть. :)
Неизвестный
20.01.2011, 09:59
общий
Безусловно вероятности есть и они весьма неравномерны. Более того в процессе игры неравномерность будет увеличиваться. Значит пересчитывать нужно после каждого хода. С другой стороны просчитать все варианты для полноразмерного поля нереально, слишком велико количество вариантов.
Я думаю, что разумнее всего считать несколько первых кораблей, упорядоченных по убыванию длины.

Например такой алгоритм:
1. Просчитать все варианты одиночного размещения корабля каждой длины на текущем поле.
Это считается быстро, для каждой длины нужно проверить O(n*n) вариантов.
Пусть на этом шаге получены числа M1, M2, M3, M4.
2. Найти множество просчитываемых кораблей при заданном ограничении. Пусть мы хотим перебирать
не более W вариантов. Тогда мы выбираем числа Mi, так чтобы их произведение
не превысило W. Например в начале игры это может быть множество {4, 3, 3}:
M4*M3*M3 < W < M4*M3*M3*M2
В конце игры, когда поле почти раскрыто, множество будет включать все живые корабли противника.
3. Перебрать все возможные размещения выбранных кораблей и построить таблицы вероятностей.
4. Выбрать клетку по вероятности, сделать ход и начать всё сначала.

Параметр W и максимальное количество просчитываемых кораблей по сути задают уровень игры программы. Для Вашей классификации уровней это может выглядеть так:
1) Считать любой один корабль и выбирать случайную клетку с ненулевой вероятностью.
2) Считать один самый большой корабль и выбирать клетку с максимальной вероятностью.
3) W = 106, выбирать клетку с максимальной вероятностью
4) А что такое красные кресты?


Неизвестный
20.01.2011, 14:19
общий
Я пока склоняюсь к тому, что в начале игры есть базовое заполнение таблиц, когда нужно сделать ход - выбирается наилучшее значение по всем кораблям. А после получения ответа вычеркивать варианты (вычитать). И текущие значения таблиц держать постоянно, то есть не нужно все время что-то пересчитывать в гигантских масштабах.
Не, вариант с вероятностями и будет третьим уровнем. Первый и второй попроще, для каждого уровня просто отдельный обработчик будет.

Игра с красными крестами - этот вариант мне когда-то мама рассказала.Обычное поле 10 на 10, корабли - 1 четырехпалубник, 2 трехпалубника, 3 двухпалубника и 2 двухпалубных корабля, помеченные как "красный крест". Ходят по очереди, причем нужно сказать 3 позиции и получить три значения в ответ, не зная, какое из них что. Если попал в красный крест - пропуск хода (вроде как мирный корабль топить нельзя). Корабли можно ставить как угодно, даже впритык. Так получается сложнее, интеллектуальнее и веселее, главное не запутаться в ходах.
Неизвестный
20.01.2011, 14:42
общий
Дело хозяйское. Я бы один алгоритм сделал, не люблю сущности преумножать
С крестами - интересный вариант, в первый раз о таком слышу.
Неизвестный
20.01.2011, 15:30
общий
Мне просто хочется потом сравнить подходы в "чистом виде". :)
Неизвестный
20.01.2011, 15:54
общий
это ответ
Здравствуйте, lupus campestris!
Код:
.../GNU-Linux-x86> time ./181931 
Одноклеточные:
242 179 151 179 242
179 111 89 111 179
151 89 84 89 151
179 111 89 111 179
242 179 151 179 242
Двухклеточные:
608 718 622 718 608
718 608 508 608 718
622 508 424 508 622
718 608 508 608 718
608 718 622 718 608
Общая таблица:
850 897 773 897 850
897 719 597 719 897
773 597 508 597 773
897 719 597 719 897
850 897 773 897 850
Всего вариантов: 3888

real 0m0.070s
user 0m0.064s
sys 0m0.000s


Код:

#include <locale>
#include <limits>
#include <iostream>
#include <iomanip>
#include <valarray>
#include <stdexcept>
#include <string>
#include <map>

using namespace std;

const bool FIGURE1[1][1] = {1};
const bool FIGURE2[1][2] = {1, 1};
const size_t BOARD_SIZE = 5;

class figure_base
{
public:
figure_base(size_t rows, size_t cols);
char& operator()(size_t row, size_t col);
char operator()(size_t row, size_t col) const;
size_t rows() const;
size_t cols() const;
template<class char_type, class traits_type> void out(basic_ostream<char_type, traits_type>& stream);
protected:
typedef valarray< valarray<char> > _fields_t;
_fields_t _fields;
size_t _rows, _cols;
};

class figure : public figure_base
{
public:

enum direction_t
{
LEFT, RIGHT
};
template<size_t DIM1, size_t DIM2> figure(size_t rotations, const bool (&fields)[DIM1][DIM2], char id);
size_t rotations() const;
char id() const;
void rotate(direction_t direction = LEFT);
protected:
size_t _rotations;
char _id;
};

class board : public figure_base
{
public:
board(size_t size);
void place(size_t row, size_t col, const figure& fig);
void remove(size_t row, size_t col, const figure& fig);
protected:
bool test(size_t row, size_t col, const figure& fig) const;
};

class solver
{
public:
typedef valarray< valarray< map<char, size_t> > > _counters_t;

struct counters_t
{
_counters_t counters;
size_t variants;
};
template<size_t DIM> solver(const figure(&figures)[DIM], size_t board_size);
counters_t run();
private:
valarray<figure> _figures;
board _board;
counters_t _counters;

void place(size_t fig_no);
};

void visualisation(const char* const msg, solver::counters_t &counters, const char* const fig_ids, unsigned int divisor);
unsigned fact(unsigned val);

/*
*
*/
int main()
{
locale::global(locale(""));

figure figures[3] = {figure(1, FIGURE1, '1'), figure(2, FIGURE2, '2'), figure(2, FIGURE2, '3')};

solver::counters_t counters = solver(figures, BOARD_SIZE).run();

unsigned div = fact(2) * fact(1);

visualisation("Одноклеточные:", counters, "1", div);
visualisation("Двухклеточные:", counters, "23", div);
visualisation("Общая таблица:", counters, "123", div);
cout << "Всего вариантов: " << counters.variants / div << endl;

return 0;
}

void visualisation(const char* const msg, solver::counters_t &counters, const char* const fig_ids, unsigned int divisor)
{
valarray< valarray<size_t> > result(counters.counters.size());
for (size_t i = 0; i < result.size(); ++i)
{
result[i] = valarray<size_t > (static_cast<size_t> (0), counters.counters[i].size());
for (size_t j = 0; j < result[i].size(); ++j)
{
const char* ids = fig_ids;
while (*ids)
{
result[i][j] += counters.counters[i][j][*ids++];
}
}
}
cout << msg << endl;
for (size_t i = 0; i < result.size(); ++i)
{
for (size_t j = 0; j < result[i].size(); ++j)
{
size_t tmp = result[i][j] / divisor;
cout << setw(5) << tmp << ' ';
}
cout << endl;
}
}

unsigned fact(unsigned val)
{
unsigned result = 1;
while (val)
{
result *= val--;
}
return result;
}

figure_base::figure_base(size_t DIM1, size_t DIM2)
: _fields(valarray<char>(static_cast<char> (0), DIM2), DIM1)
, _rows(DIM1)
, _cols(DIM2)
{

}

char& figure_base::operator ()(size_t row, size_t col)
{
return _fields[row][col];
}

char figure_base::operator ()(size_t row, size_t col) const
{
return _fields[row][col];
}

size_t figure_base::rows() const
{
return _rows;
}

size_t figure_base::cols() const
{
return _cols;
}

template<class char_type, class traits_type>
void figure_base::out(basic_ostream<char_type, traits_type>& stream)
{
const ctype<char_type>& facet = use_facet< ctype<char_type> >(stream.getloc());
static basic_string<char_type> hline(1 + 2 * _rows, facet.widen('-'));
stream << hline << endl;
for (size_t i = 0; i < _rows; ++i)
{
for (size_t j = 0; j < _cols; ++j)
{
stream << facet.widen('|') << (_fields[i][j] ? facet.widen(_fields[i][j]) : facet.widen(' '));
}
stream << facet.widen('|') << endl << hline << endl;
}
}

template<size_t DIM1, size_t DIM2 >
figure::figure(size_t rotations, const bool (&fields)[DIM1][DIM2], char id)
: figure_base(DIM1, DIM2)
, _rotations(rotations)
, _id(id)
{
if (_rotations > 4)
{
throw invalid_argument("К-во поворотов фигуры не может быть более 4х");
}

for (size_t i = 0; i < DIM1; ++i)
{
for (size_t j = 0; j < DIM2; ++j)
{
_fields[i][j] = fields[i][j] ? id : 0;
}
}
}

size_t figure::rotations() const
{
return _rotations;
}

char figure::id() const
{
return _id;
}

void figure::rotate(direction_t direction)
{
figure_base newFigure(_cols, _rows);
for (size_t i = 0; i < _cols; ++i)
{
for (size_t j = 0; j < _rows; ++j)
{
switch (direction)
{
case LEFT:
newFigure(i, j) = _fields[j][ _cols - 1 - i];
break;
case RIGHT:
newFigure(i, j) = _fields[_rows - 1 - j][i];
break;
default:
throw invalid_argument("Неверное направление");
}
}
}
*reinterpret_cast<figure_base*> (this) = newFigure;
}

board::board(size_t size)
: figure_base(size, size)
{

}

void board::place(size_t row, size_t col, const figure& fig)
{
if (!(row < _rows && col < _cols))
{
throw invalid_argument("Неверно заданы координаты");
}
if (!(fig.rows() <= _rows - row && fig.cols() <= _cols - col))
{
throw invalid_argument("Фигура слишком велика");
}

if (!test(row, col, fig))
{
throw invalid_argument("Невозможно установить");
}

for (size_t i = 0; i < fig.rows(); ++i)
{
for (size_t j = 0; j < fig.cols(); ++j)
{
if (!_fields[i + row][j + col] && fig(i, j))
{
_fields[i + row][j + col] = fig.id();
}
}
}
}

void board::remove(size_t row, size_t col, const figure& fig)
{
if (!(row < _rows && col < _cols))
{
throw invalid_argument("Неверно заданы координаты");
}
if (!(fig.rows() <= _rows - row && fig.cols() <= _cols - col))
{
throw invalid_argument("Фигура слишком велика");
}

for (size_t i = 0; i < fig.rows(); ++i)
{
for (size_t j = 0; j < fig.cols(); ++j)
{
if (fig(i, j))
{
_fields[i + row][j + col] = 0;
}
}
}
}

bool board::test(size_t row, size_t col, const figure& fig) const
{
for (size_t i = 0; i < fig.rows(); ++i)
{
for (size_t j = 0; j < fig.cols(); ++j)
{
if (fig(i, j))
{
for (size_t r = i + row - 1, er = r + 3; r != er; ++r)
{
for (size_t c = j + col - 1, ec = c + 3; c != ec; ++c)
{
if (r < _rows && c < _cols && _fields[r][c])
{
return false;
}
}
}
}
}
}
return true;
}

template<size_t DIM >
solver::solver(const figure(&figures)[DIM], size_t board_size)
: _figures(figures, DIM)
, _board(board_size)
{
}

solver::counters_t solver::run()
{
_counters.counters = valarray< valarray< map<char, size_t> > >(valarray< map<char, size_t > >(_board.cols()), _board.rows());
_counters.variants = 0;
place(_figures.size());
return _counters;
}

void solver::place(size_t fig_no)
{
if (!fig_no)
{
for (size_t i = 0; i < _board.rows(); ++i)
{
for (size_t j = 0; j < _board.cols(); ++j)
{
++_counters.counters[i][j][_board(i, j)];
}
}
++_counters.variants;
}
else
{
figure fig(_figures[--fig_no]);

for (size_t pos = 0; pos < fig.rotations(); ++pos)
{
for (size_t row = 0; row < _board.rows(); ++row)
{
for (size_t col = 0; col < _board.cols(); ++col)
{
try
{
_board.place(row, col, fig);
this->place(fig_no);
_board.remove(row, col, fig);
}
catch (...)
{

}
}
}
fig.rotate();
}
}
}

Метод решения - полный перебор.
Времени ушло ~6ч.

Вообще то, изначально была мысль написать программу для решения задач типа полиомино, где фигуры могут быть заметно сложнее чем 2х клеточные. Так же была цель обеспечить относительно легкую модификацию и сопровождение кода. Напр. легкое изменение размера доски, добавление различных фигур и т.п. Отсюда заметная избыточность кода. Часть той программы была использована здесь.
5
Ого! Спасибо большое!
Неизвестный
20.01.2011, 15:56
общий
А можно мне?
Неизвестный
20.01.2011, 16:27
общий
Конечно можно!Мощный код! :)
Linux forever :)
Форма ответа