Непостоянный король
От: adontz Грузия http://adontz.wordpress.com/
Дата: 22.04.03 00:38
Оценка: 20 (3)
Дана шахматная доска 8х8 клеток
В левом нижнем углу король
Он может двигаться вверх, вправо или вверх и вправо по диагонали
Слолько различных путей у короля из левого нижнего угла в правый верхний если он не совершает более 3 движений подряд в одном и том же направлении ?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: Непостоянный король
От: nikholas Россия  
Дата: 22.04.03 05:37
Оценка: 14 (1) :)
Здравствуйте, adontz, Вы писали:

A>Дана шахматная доска 8х8 клеток

A>В левом нижнем углу король
A>Он может двигаться вверх, вправо или вверх и вправо по диагонали
A>Слолько различных путей у короля из левого нижнего угла в правый верхний если он не совершает более 3 движений подряд в одном и том же направлении ?


#define restrictedLength 4
unsigned countMoves()
{
    unsigned board[2*8+restrictedLength][2*8+restrictedLength];
    //чтобы не заморачиваться с ходьбой по диагонали
    memset(board, 0, sizeof(board));
    board[7][7] = 1;
    for(unsigned moveNo = 0; moveNo != 14; ++moveNo)
        //идем изверхнего правого в нижний левый угол
        for(unsigned x = 0, y = 13 - moveNo; x != 14 - moveNo; ++x, --y)
            board[x][y] = board[x+1][y] + board[x+1][y+1] + board[x][y+1] -
            board[x+restrictedLength][y] - 
            board[x+restrictedLength][y+restrictedLength] - 
            board[x][y+restrictedLength];
    return board[0][0];
}


Ответ — 39751 путев
... << RSDN@Home 1.0 beta 6a >>
Re: Непостоянный король
От: kinstintin  
Дата: 23.04.03 04:40
Оценка:
Здравствуйте, adontz, Вы писали:

A>Дана шахматная доска 8х8 клеток

A>В левом нижнем углу король
A>Он может двигаться вверх, вправо или вверх и вправо по диагонали
A>Слолько различных путей у короля из левого нижнего угла в правый верхний если он не совершает более 3 движений подряд в одном и том же направлении ?

40272
... << RSDN@Home 1.0 beta 6a >>
Re[2]: Непостоянный король
От: nikholas Россия  
Дата: 23.04.03 16:10
Оценка:
Здравствуйте, kinstintin, Вы писали:

K>40272


А доказать?
Жаль adontz свои задачи на правильность не оценивает...
Кто же прав?

PS Я то здесь
Автор: nikholas
Дата: 22.04.03
был не прав , а никто и не заметил...
Re: Непостоянный король
От: Кодт Россия  
Дата: 23.04.03 16:54
Оценка: 3 (1)
Здравствуйте, adontz, Вы писали:

<>

Напрашивается волновой алгоритм.
Фронт волны #k — это ячейки [0,k]..[k,k]..[k,0]

В каждой ячейке нужно хранить сумму "входов в нее", с учетом предыстории.
Т.е.
struct cell
{
  int x[1..3], y[1..3], d[1..3]; // да простят мне этот псевдокод :)
};

x[1] означает, что в эту ячейку можно попасть N путями, причем последний ход — это одиночный шаг по x.
x[2] — соответственно, двойной шаг по x.
И так далее.
(x[0] я здесь не использую — просто для лучшей ясности кода)

Теперь определим правила подсчета.

Изначально все ячейки обнулены.

Переход от одной ячейки (уже посчитанной) к другой:
step_x(cell const& from, cell& to)
{
  // если это первый шаг по x...
  to.x[1] += from.y[1]+from.y[2]+from.y[3]
          +  from.d[1]+from.d[2]+from.d[3];
  // и если не первый...
  to.x[2]  = from.x[1];
  to.x[3]  = from.x[2];
}

и аналогично для y и d.

Чтобы правильно начать подсчет, инициализируем первый фронт (один шаг от старта):
step_first(cell& to, int x, int y, int d)
{
  to.x[1] = x; to.y[1] = y; to.d[1] = d;
  // только один из параметров равен 1, остальные - нули
}


После этого по каждому (в том числе и по первому) фронту производим забег:
walk_front(int k)
{
  for(i = 0, i < k, ++i) // направление итераций важно!!! i = 0-->k
  {
    if(i>0       )  step_x( cell[i-1,k  ], cell[i,k] );
    if(       k>0)  step_y( cell[i  ,k-1], cell[i,k] );
    if(i>0 && k>0)  step_d( cell[i-1,k-1], cell[i,k] );

    if(k>0       )  step_x( cell[k-1,i  ], cell[k,i] );
    if(       i>0)  step_y( cell[k  ,i-1], cell[k,i] );
    if(k>0 && i>0)  step_d( cell[k-1,i-1], cell[k,i] );
  }
}

Направление итераций важно, т.к. допускается передвижение вдоль фронта (в сторону роста координаты).

Ну, и наконец, посчитаем сумму счетчиков для ячейки cell[N,N].



Вот, осталось только запрограммировать... Это — чуть позже.
... << RSDN@Home 1.0 beta 6a >>
Перекуём баги на фичи!
Re[2]: Непостоянный король
От: Andy77 Ниоткуда  
Дата: 23.04.03 17:11
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Напрашивается волновой алгоритм.


Мне показалось, что задачу предлагается решать аналитически... что скажет автор?
Re[3]: Непостоянный король
От: adontz Грузия http://adontz.wordpress.com/
Дата: 23.04.03 17:42
Оценка:
Здравствуйте, Andy77, Вы писали:

A>Мне показалось, что задачу предлагается решать аналитически... что скажет автор?


Автор не имеет ни малейшего понятия ни о решении, ни о методах решеия. Я просто усложнил задачу ограничением в 3 хода в одном направлении. Думаю можно решить и аналитически, хотя это и сложнее чем изначальная задача.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[2]: Непостоянный король
От: kinstintin  
Дата: 24.04.03 05:52
Оценка:
Здравствуйте, Кодт, Вы писали:

К><>


К>Напрашивается волновой алгоритм.

К>Фронт волны #k — это ячейки [0,k]..[k,k]..[k,0]

К>В каждой ячейке нужно хранить сумму "входов в нее", с учетом предыстории.

К>Т.е.
К>
К>struct cell
К>{
К>  int x[1..3], y[1..3], d[1..3]; // да простят мне этот псевдокод :)
К>};
К>


Примерно так и решал , только на листочке
Возникает вопрос, а нужно ли хранить дополнительные данные о 9ти классах путей
в каждой ячейке или можно обойтись меньшим количеством вспомогательных данных?
... << RSDN@Home 1.0 beta 6a >>
Re[3]: Непостоянный король
От: adontz Грузия http://adontz.wordpress.com/
Дата: 24.04.03 06:06
Оценка:
Здравствуйте, kinstintin, Вы писали:

K>Возникает вопрос, а нужно ли хранить дополнительные данные о 9ти классах путей

K>в каждой ячейке или можно обойтись меньшим количеством вспомогательных данных?

Думаю нужно
A journey of a thousand miles must begin with a single step © Lau Tsu
Re: Непостоянный король
От: epflorov Россия www.epflorov.hotbox.ru
Дата: 26.04.03 07:44
Оценка:
Здравствуйте, adontz, Вы писали:

A>Дана шахматная доска 8х8 клеток

A>В левом нижнем углу король
A>Он может двигаться вверх, вправо или вверх и вправо по диагонали
A>Слолько различных путей у короля из левого нижнего угла в правый верхний если он не совершает более 3 движений подряд в одном и том же направлении ?

21692

Правильность работы алгоритма можно проверить на меньших досках (например 3х3) и меньших ограничениях (2)

-----------------------------------------------------------
#include <vector>
#include <queue>
#include <iostream>

struct pos 
{  
  pos():x(0), y(0) {}
  pos(int _x, int _y) : x(_x), y (_y) {}
  pos(const pos& s) :x(s.x), y(s.y) {}
  int x, y; 
  pos& operator += ( const pos& p ) { x += p.x; y += p.y; return *this;}
  bool operator == ( const pos& p ) const { return (x == p.x) && (y == p.y); }
  bool operator != ( const pos& p ) const { return ! operator ==(p); }
};

const pos UP(0, 1);
const pos RI(1, 0);
const pos UR(1, 1);
const pos SIZE(8, 8); // size of board

const int ONEDIR = 3; // not allowed steps in one direction


typedef std::vector<pos> moves;

struct pathes
{
  pos _start;
  pos _end;
  moves _moves;
  std::ostream& out(std::ostream& o);
};

std::ostream&
pathes::out(std::ostream &o)
{
  o << "----------------------------" << std:: endl;
  for(int i = 0; i < _moves.size(); i++)
  {
    if(_moves[i] == UP) 
      o << " UP ";
    else if(_moves[i] == RI) 
      o << " RI ";
    else if(_moves[i] == UR) 
      o << " UR ";
    else
      o << " :( ";
  }
  o << std::endl;
  return o;
}

std::queue<pathes> _pathes;
std::vector<pathes> _result;

bool check(const moves &m, const pos &p)
{
  int to = m.size() - ONEDIR + 1;
  if (  to >= 0 )
  {
    for(int i = m.size() - 1; i >= to; i--)
      if(m[i] != p)
        return true;
    return false;
  }
  return true;
}

moves get_allow_moves(const pathes& path)
{
  moves res;
  if((path._end.x != SIZE.x) && check(path._moves, RI))
    res.push_back(RI);
  if((path._end.y != SIZE.y) && check(path._moves, UP))
    res.push_back(UP);
  if((path._end.x != SIZE.x) && (path._end.y != SIZE.y) && check(path._moves, UR))
    res.push_back(UR);
  return res;
}

void scan()
{
  while(!_pathes.empty())
  {
    pathes cur = _pathes.front();
    moves mov = get_allow_moves(cur);
    if( cur._end == SIZE)
      _result.push_back(cur);
    else 
      for( int i = 0; i < mov.size(); i++)    
      {
        pathes np(cur);
        np._end += mov[i];
        np._moves.push_back(mov[i]);
        _pathes.push(np);
      }
    _pathes.pop();
  }
}

int
main()
{
  pathes first;
  first._start.x = 1;
  first._start.y = 1;  
  first._end.x = 1;
  first._end.y = 1;
  _pathes.push(first);
  scan();
  std::cout << "found " << _result.size() << " pathes";

// uncomment if want to view pathes
//  for(int i = 0; i < _result.size(); i++)
//    _result[i].out(std::cout);
  char ch;
  std::cin >> ch;
  return 0;
}
Евгений Флоров
Re: Непостоянный король
От: 3.14159.. Израиль  
Дата: 26.04.03 10:31
Оценка:
Здравствуйте, adontz, Вы писали:

A>Дана шахматная доска 8х8 клеток

A>В левом нижнем углу король
A>Он может двигаться вверх, вправо или вверх и вправо по диагонали
A>Слолько различных путей у короля из левого нижнего угла в правый верхний если он не совершает более 3 движений подряд в одном и том же направлении ?

А с рекурсией пожалуй покрасивей будет, да и результат посолидней: 12389303


#include <stdio.h>
#include <vector>
using namespace std;

void Step(int x, int y);
void OutputPath();

vector<pair<int, int> > Path;
int N, M, Count;
void main(int argc, char* argv[])
{
    if(argc!=3){
        printf("argv[1] - Table size\n");
        printf("argv[2] - Max step\n");
        return;
    }
    N = atoi(argv[1]);
    M = atoi(argv[2]);
    Count = 0;
    Step(0, 0);
    printf("%d\n", Count);
}

void Step(int x, int y)
{
    int i;
    if(x==N && y==N){
//        OutputPath();
        Count++;
        return;
    }
    else{
        for(i=1; i<=N-x && i<=M; i++){
            Path.push_back(pair<int, int>(x + i, y));
            Step(x + i, y);
            Path.pop_back();
        }
        for(i=1; i<=N-y && i<=M; i++){
            Path.push_back(pair<int, int>(x, y + i));
            Step(x, y + i);
            Path.pop_back();
        }
        for(i=1; i<=N-x && i<=N-y && i<=M; i++){
            Path.push_back(pair<int, int>(x + i, y + i));
            Step(x + i, y + i);
            Path.pop_back();
        }
    }
}

void OutputPath()
{
    static int line=0;
    printf("%7d:  ", ++line);
    for(int i=0; i< Path.size(); i++){
        printf("(%2d, %2d)  ", Path[i].first, Path[i].second);
    }
    printf("\n");
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.