2010-02-12 3 views
4

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

Здесь:

Существует двор, в котором есть волки и овцы. Во дворе есть также блоки, которые не позволяют пройти. Волки представлены «w» и овцами с «s», а блоки - с «#», а пространство, в котором каждый может двигаться, - это «.». , Таким образом, возможный ввод будет выглядеть так:

2 цифры над двором - это строки x столбцов.

Как вы можете видеть, этим могут быть сформированы участки разного вида во дворе. Вот два сектора:

#### 
#.w# 
#### 
#s.# 

В первом есть волк, а во второй - овца. Поскольку они размещены в двух разных секторах (т. Е. Волк не может добраться до овец), он не может его съесть. Если бы они были в одном секторе, волк съел бы овец.

Мой вопрос для вас заключается в следующем: учитывая входные данные, подобные приведенным выше, как я должен рассчитать, сколько овец выживет? Как я могу представить «двор» в C++? Как должен выглядеть алгоритм? Существуют ли какие-либо материалы для понимания подобных проблем и проблем?

Любая помощь приветствуется. Заранее спасибо.

+2

Я просил ответить ниже, но я должен сказать, что если такая проблема не кричит «ГРАФ» на вас, у вас есть много подготовки, чтобы быть готовой к любому серьезному соревнованию по программированию. – DVK

+1

Я согласен с DVK. Я только что вернулся из финала ICPC в мире, и если бы эта проблема была там, это было бы решено примерно через 4 минуты. Я не хочу тебя отговаривать, но просто предупредите, что впереди у вас много тренировок. –

+1

Я бы сказал, что любой, кто сразу же думает, что «ГРАФ» любит математику над сложными решениями. Для меня это кричит наводнение. – phkahler

ответ

1

Что вы ищете, это найти связанных компонентов графа, тогда вам просто нужно подсчитать количество волков и овец в каждом из них.

using namespace std; 

int w, h; 
cin >> w >> h; 
vector<string> grid(h); 
for (int i = 0; i < h; ++i) 
    cin >> grid[i]; 

vector< vector<bool> > seen(h, vector<bool>(w, false)); 
int survived = 0; 
const int mx[] = {-1, 0, 1, 0}, my[] = {0, -1, 0, 1}; 

for (int i = 0; i < h; ++i) 
    for (int j = 0; j < w; ++j) 
    if (!seen[i][j] && grid[i][j] != '#') 
    { 
     int sheep = 0, wolves = 0; 
     typedef pair<int, int> point; 
     stack<point> s; 
     s.push(point(i, j)); 

     while (!s.empty()) 
     { 
     point p = s.top(); 
     int x = p.first, y = p.second; 
     if (grid[x][y] == 'w') wolves++; 
     if (grid[x][y] == 's') sheep++; 
     for (int k = 0; k < 4; ++k) 
     { 
      int x2 = x + mx[k], y2 = y + my[k]; 
      if (x2<0 || x2>=h || y2<0 || y2>=w) continue; 
      if (grid[x2][y2] == '#' || seen[x2][y2]) continue; 
      s.push(point(x2, y2)); 
     } 
     } 
     survived += max(0, sheep - wolves); 
    } 

cout << "Surviving sheep = " << survived << endl; 

Время работы и использование памяти оптимальны для O (строки x столбцов).

Обратите внимание, что код не проверен, но я считаю, что это должно сработать.

+0

Хе-хе ... не будет ли это набухать, если бы это был парень, проводящий LIVE от соревнований по программированию, и вы просто решили проблему для него? :) – DVK

+0

Сколько времени вам понадобилось, чтобы написать это? (Я как бы соблазн сделать реализацию Perl и посмотреть, смогу ли я выиграть ваше время, как только я уйду от работы :)) – DVK

+0

О да, +1 для лишнего effory :) – DVK

0

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

4

Эта проблема в основном заключается в поиске connected sub-graphs (aka components) для данного графика.

Вы можете решить эту проблему, представив каждую «неблокирующую» координату как узел графика, связывая 2 соседние координаты в графе. Затем найдите подключенные подграфы, используя BFS (или любой другой алгоритм, подходящий для темы). Я уверен, что любая веб-страница или Wiki на графических algos будет иметь список различных алгоритмов.

Как только у вас есть подграфы, просто найдите которые подграфы имеют нулевых волков (от нахождения которых подграф каждого волка координаты на), и сосчитать овца в этих подграфах.

Надеется, что это достаточно для того, чтобы начать.

+0

Добавлена ​​ссылка на соответствующую Wiki (связанная маркировка компонентов - это термин, который я забыл) – DVK

+0

+1 для того, чтобы не предлагать заливку от каждого волка. –

+0

Да, я нахожу каждый цикл ЦП ценным :) – DVK

0

Не похож на геометрию для меня.Я бы решил это с помощью алгоритма Flood fill

Заполните каждую область уникальным номером. Затем, для каждого числа, на котором вы заполнили область, узнаете, сколько овец и сколько волки смежны с этим числом. Единственными оставшимися в живых овцами являются те, которые примыкают к числу k, к которому не привязаны волки.

Вы можете представить матрицу в C++ как матрицу символов: char A [maxrows] [maxcols]. Однако, чтобы использовать заливку заливки, я бы использовал матрицу ints, потому что у вас может быть больше областей, чем максимальное значение char.

+0

Или используйте алгоритм BFS следующим образом: добавьте каждого волка в очередь. Затем, когда вы извлекаете волк, вы отмечаете каждое из его смежных положений. Когда вы ударяете (heheh) овец, уменьшаете количество овец, оставшихся в живых. Это будет O (строки x cols). Простой и оптимальный. – IVlad

1

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

В вашем примере:

#### 
#.w# 
#### 
#s.# 

бы набить:

#### 
#fw# 
#### 
#s.# 

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

+1

Выполнение наводнения на каждом волке не будет работать в этой проблеме. Представьте себе сетку 100 x 100 с волком на каждом квадрате. Вам нужно будет запустить 10000 заливок наводнений, каждый из которых заполняет весь массив 10000, давая вам 100 000 000 рабочих часов, которые не будут приняты в конкурсе. –

+0

@poita некорректный. каждый поток заливки должен просто переполнять каждый квадрат, который он получает, помимо стен. то у вас не более 1 заливки на квадрат, что очень разумно и намного проще реализовать. имейте в виду - у вас очень мало времени для реализации (И DEBUG) решения на таких соревнованиях. На самом деле я считаю, что наводнение является лучшим решением в данном сценарии. – rmn

+0

@rmn, если вы думаете, что это намного проще реализовать, тогда идите и докажите, что я неправ. Если вы знаете что-нибудь об алгоритмах, тогда вам будет хорошо известно, что единственная разница между DFS (что я предложила) и BFS/заливка заливки (что вы предложили) заключается в том, что DFS использует стек, а BFS использует очередь (вперед, измените стек в моем коде на очередь, и это будет BFS). Таким образом, он принимает ТОЧНОЕ такое же количество времени для реализации, вплоть до самого персонажа. –

0

Это ограниченный по времени конкурс? Например, где ваш счет зависит от количества программ, решаемых в данный момент времени?

Для них я бы рекомендовал простой подход, основанный на двух вещах:

  • представляют данные в виде 2D массива

  • Определить, когда овцы и волки разделяют сектора путем поиска соединения, используя что-то подобно алгоритму наводнения от каждого волка. Я бы посоветовал начинать с волков и «убивать» овец, когда вы их достигаете. После того, как вы сделаете это для каждого волка, оставшиеся овцы в структуре данных выживут.

Ключом в ограниченных по времени соревнованиями является разработка простого решения, которое быстро запрограммировано. Современные компьютеры работают очень быстро. Не думайте о геометрических алгоритмах, если вам не нужно обрабатывать огромные наборы данных, просто подумайте, как я могу легко вычислить проблему при решении проблемы.

Хотя я думал об этом, несколько других людей предложили наводнение, так что это несколько избыточно.

+0

Конечно, «правильное» алгоритмическое решение такой проблемы определяет связанные компоненты, а затем подсчитывает количество овец, которые находятся в соединенных компонентах, которые не содержат волков. – Paul

Смежные вопросы