Форум программистов, компьютерный форум, киберфорум
Python: Решение задач
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.68/25: Рейтинг темы: голосов - 25, средняя оценка - 4.68
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164

Сталкер (не проходит по памяти)

12.03.2023, 21:34. Показов 5398. Ответов 36
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В городе Н при невыясненных обстоятельствах территория одного из заводов превратилась в аномальную зону. Все подъезды к территории были перекрыты, а сама она получила название промзоны. В промзоне находятся N зданий, некоторые из них соединены дорогами. По любой дороге можно перемещаться в обоих направлениях.
Начинающий сталкер получил задание добраться до склада в промзоне. Он нашел в электронном архиве несколько карт территории промзоны. Так как карты составлялись разными людьми, то на каждой из них есть информация только о некоторых дорогах промзоны. Одна и та же дорога может присутствовать на нескольких картах.
В пути сталкер может загружать из архива на мобильный телефон по одной карте. При загрузке новой карты предыдущая в памяти телефона не сохраняется. Сталкер может перемещаться лишь по дорогам, отмеченным на карте, загруженной на данный момент. Каждая загрузка карты стоит 1 рубль. Для минимизации расходов сталкеру нужно выбрать такой маршрут, чтобы как можно меньшее число раз загружать карты. Сталкер может загружать одну и ту же карту несколько раз, при этом придется заплатить за каждую загрузку. Изначально в памяти мобильного телефона нет никакой карты.
Требуется написать программу, которая вычисляет минимальную сумму расходов, необходимую сталкеру, чтобы добраться от входа в промзону до склада.

Формат ввода
В первой строке входного файла находятся два натуральных числа N и K (2 ≤ N ≤ 2000; 1 ≤ K ≤ 2000) - количество зданий промзоны и количество карт соответственно. Вход в промзону находится в здании с номером 1, а склад - в здании с номером N.
В последующих строках находится информация об имеющихся картах. Первая строка описания i-ой карты содержит число ri - количество дорог, обозначенных на i-ой карте. Затем идут ri строк, содержащие по два натуральных числа a и b (1 ≤ a, b ≤ N; a ≠ b), означающих наличие на i-ой карте дороги, соединяющей здания a и b. Суммарное количество дорог, обозначенных на всех картах, не превышает 300 000 (r1 + r2 + ... + rK ≤ 300 000).
Формат выходных данных

В выходной файл необходимо вывести одно число - минимальную сумму расходов сталкера. В случае, если до склада добраться невозможно, выведите число -1.

Пример.
Ввод:
12 4
4
1 6
2 4
7 9
10 12
3
1 4
7 11
3 6
3
2 5
4 11
8 9
5
3 10
10 7
7 2
12 3
5 12

Вывод:
3

Мой алгоритм такой: каждую карту разбиваю на компоненты связности и далее строю граф, где вершиной является номер компонента связности. И далее иду по этому графу обходом в ширину. Так же учитываю, что начало и конец могут быть сразу в нескольких компонентах связности.
Мой алгоритм вроде выдает верный ответ, но по памяти все плохо. Что я делаю не так?
Мой код:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
def solution():
    def dfs(vert):
        neighbour_vert = graf[vert]
        graf[vert] = False
        for now_vert in neighbour_vert:
            if graf[now_vert] != False:
                dfs(now_vert)
        if len(intersection_con[vert]) >= 1:
            for con_two in intersection_con[vert]:
                graf_con[con_two].append(count_con)
                graf_con[count_con].append(con_two)
        intersection_con[vert].append(count_con)
 
    houses, maps = map(int, input().split())
    intersection_con = [[] for _ in range(houses+1)]    # для каждого дома записываем с какими связностями он пересекается
    count_con = 0
    graf_con = []   # граф связностей
    for _ in range(maps):
        # roads = int(data[i])
        roads = int(input())
        graf = {}
        for _ in range(roads):
            # house_one, house_two = map(int, data[i].split())
            house_one, house_two = map(int, input().split())
            try:
                graf[house_one].append(house_two)
            except KeyError:
                graf[house_one] = [house_two]
            try:
                graf[house_two].append(house_one)
            except KeyError:
                graf[house_two] = [house_one]
        for vert in graf:
            if graf[vert] != False:
                graf_con.append([])
                dfs(vert)   # проверяем связность
                count_con += 1
 
    graf_con = [set(intersection) for intersection in graf_con]     # чтобы ребра не повторялись
    start_cons = intersection_con[1]
    end_cons = intersection_con[houses]
    intersection_con = []
    queue = [start_con for start_con in start_cons]
    distance = [-1]*(count_con)
    for st_con in queue:
        distance[st_con] = 1    # за первую загруженную карту надо заплатить
 
    for con in queue:
        for neighbour_con in graf_con[con]:
            if distance[neighbour_con] == -1:
                distance[neighbour_con] = distance[con] + 1
                queue.append(neighbour_con)
 
    ans = -1   # минимум переключений карт
    for end_con in end_cons:
        if (distance[end_con] < ans and distance[end_con] != -1) or ans == -1:
            ans = distance[end_con]
    print(ans)
solution()
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
12.03.2023, 21:34
Ответы с готовыми решениями:

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

FreeZoneMods Онлайн Сталкер ЧН
Привет! Обращаюсь за помощью к знатокам Lazarus`а 32 бит. Предупреждаю сразу, что я к программированию никакого отношения не имею. Прошу...

Вылеты в Сталкер ЗП/Сигероус мод 2.1
В лабе Х18 гасишь зомбарей, и с определенного момента сохранения становятся битыми. При их загрузке: stack trace: ...

36
Эксперт Python
 Аватар для Red white socks
4523 / 1899 / 336
Регистрация: 18.01.2021
Сообщений: 3,489
13.03.2023, 14:42
Студворк — интернет-сервис помощи студентам
DarkShaddow, да, у меня города = здания)
0
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
13.03.2023, 15:42  [ТС]
Цитата Сообщение от Red white socks Посмотреть сообщение
добавляем в первую с тем же номером города, но с другой карты
а как понять какие карты соответствуют данному зданию (просто перебирать что ли?)
0
Эксперт Python
 Аватар для Red white socks
4523 / 1899 / 336
Регистрация: 18.01.2021
Сообщений: 3,489
13.03.2023, 15:58
DarkShaddow, можно собрать словарь - здание: список карт.
По идее, с ограничением списка всех дорог не должно много места в памяти занять

Добавлено через 3 минуты
Но для питона не знаю, уж больно много он на целое отводит.
То есть, если бы я делал задачу на java, то о таких мелочах даже не задумывался бы - там с очень большим запасом проходим и по памяти и по времени, а тут постоянно оглядываться нужно
0
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
13.03.2023, 16:16  [ТС]
Red white socks, вроде сделал все, как вы сказали.
Единственное не понял зачем хранить связанные вершины
Цитата Сообщение от Red white socks Посмотреть сообщение
Для удобства пусть также у нас есть функция получения связных вершин (не путать с соседними) к данной по данной карте.
Но не проходит 3 тест:
15 4
5
4 9
3 9
6 2
2 10
11 12
7
1 4
4 7
7 10
6 13
8 13
8 14
13 14
8
1 5
2 13
2 3
5 10
5 11
5 12
11 12
6 13
1
14 15


Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import math
 
def solution_new():
    from collections import deque
 
    n, k = map(int, input().split())
    graph = {}
    maps = {i: set() for i in range(1, n + 1)}
    start_maps = set()
    end_maps = set()
    for i in range(1, k + 1):
        for _ in range(int(input())):
            x, y = map(int, input().split())
            maps[i].add(x)
            maps[i].add(y)
            key1, key2 = (i, x), (i, y)
            graph.setdefault(key1, set()).add(key2)
            graph.setdefault(key2, set()).add(key1)
            if x == 1 or y == 1:
                start_maps.add(i)
            if x == n or y == n:
                end_maps.add(i)
 
 
    # print(graph, sep='\n')
    # print(maps)
    count_cost = 1
    queue = [(map, 1) for map in start_maps]
    # print(queue)
    queue_2 = []
    viseted = {map_house:False for map_house in graph.keys()}
 
    # print(viseted)
    while len(queue) != 0:
        for map_house in queue:
            viseted[map_house] = count_cost
            for neighbour_map_house in graph[map_house]:
                if viseted[neighbour_map_house] == False:
                    viseted[neighbour_map_house] = count_cost
                    queue_2.append(neighbour_map_house)
 
            # graph[map_house] = count_cost
        count_cost += 1
        queue = []
 
        for map_house in queue_2:
            for num_map in range(1, k+1):
                try:
                    if viseted[(num_map, map_house[1])] == False:
                        queue.append((num_map, map_house[1]))
                except KeyError:
                    pass
 
    ans = math.inf
    for num_map in end_maps:
        if viseted[(num_map, n)] != False and viseted[(num_map, n)] < ans:
            ans = viseted[(num_map, n)]
 
    if ans == math.inf:
        print(-1)
    else:
        print(ans)
 
solution_new()
Добавлено через 2 минуты
Цитата Сообщение от Red white socks Посмотреть сообщение
можно собрать словарь - здание: список карт
добавлю потом
Кстати, по факту получился объемный граф?
0
Эксперт Python
 Аватар для Red white socks
4523 / 1899 / 336
Регистрация: 18.01.2021
Сообщений: 3,489
13.03.2023, 16:22
Цитата Сообщение от DarkShaddow Посмотреть сообщение
Кстати, по факту получился объемный граф?
Можно сказать, что 3D) Но я назвал бы это атласом)

Добавлено через 3 минуты
Вечером посмотрю детально, реализация на беглый взгляд мне не нра.
Очереди реализовываться должны через deque, перебирать элементы методом pop() (при переборе элементы очереди из неее уходят). map - оч.плохое имя для переменной
0
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
13.03.2023, 16:28  [ТС]
понял, подправлю
0
Эксперт Python
 Аватар для Red white socks
4523 / 1899 / 336
Регистрация: 18.01.2021
Сообщений: 3,489
13.03.2023, 16:32
Ключевая ошибка, конечно
Цитата Сообщение от DarkShaddow Посмотреть сообщение
Единственное не понял зачем хранить связанные вершины
Хранить не надо, но надо вычислять. Потому что стоимость перемещения во все связанные вершины нулевая. И отдельно заострил внимание, что связанные (из одной компоненты связности) и соседние (в задании графа) не одно и то же.
0
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
13.03.2023, 17:39  [ТС]
Red white socks, подправил все. Теперь 3 тест проходит, но на 7 выдает TL.
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# coding: utf-8
# 40м - paperCode; 100 + 88 + 20 - Python; 100 min + 26 + 55 + 77 - C++; 100 +
import math
 
def solution_new():
    from collections import deque
 
    n, k = map(int, input().split())
    graph = {}
    maps_for_house = {i:set() for i in range(1, n+1)} # для каждого здания запоминаем карты, на который оно расположено
    start_maps = set()
    end_maps = set()
    for i in range(1, k + 1):
        for _ in range(int(input())):
            x, y = map(int, input().split())
            maps_for_house[x].add(i)
            maps_for_house[y].add(i)
            key1, key2 = (i, x), (i, y)
            graph.setdefault(key1, set()).add(key2)
            graph.setdefault(key2, set()).add(key1)
            if x == 1 or y == 1:
                start_maps.add(i)
            if x == n or y == n:
                end_maps.add(i)
 
    count_cost = 0
    queue = deque()
    for num_map in start_maps:
        queue.append((num_map, 1))
 
    viseted = {map_house:False for map_house in graph.keys()}
    while len(queue) != 0:
        count_cost += 1
        queue_2 = deque()
        while len(queue) != 0:
            map_house = queue.pop()
            viseted[map_house] = count_cost
            for neighbour_map_house in graph[map_house]:
                if viseted[neighbour_map_house] == False:
                    viseted[neighbour_map_house] = count_cost
                    queue.append(neighbour_map_house)
                    queue_2.append(neighbour_map_house)
 
        queue = deque()
        while len(queue_2) != 0:
            map_house = queue_2.pop()
            for num_map in maps_for_house[map_house[1]]:
                try:
                    if viseted[(num_map, map_house[1])] == False:
                        queue.append((num_map, map_house[1]))
                except KeyError:
                    pass
 
    ans = math.inf
    for num_map in end_maps:
        if viseted[(num_map, n)] != False and viseted[(num_map, n)] < ans:
            ans = viseted[(num_map, n)]
 
    if ans == math.inf:
        print(-1)
    else:
        print(ans)
 
solution_new()
Видимо не успею её сдать до 18:00. А она была последней из 70
0
814 / 422 / 169
Регистрация: 08.02.2013
Сообщений: 711
13.03.2023, 17:56
Лучший ответ Сообщение было отмечено DarkShaddow как решение

Решение

DarkShaddow, можешь это попробовать, но скорее всего не пройдет все тесты
Кликните здесь для просмотра всего текста
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from collections import deque
# input = open('input.txt').readline
 
def get_line():
    line = input().strip()
    return line if line else get_line()
 
n, k = map(int, get_line().split())
outs = [set() for _ in range(n+1)]
 
def read_map():
    g = dict()
    for _ in range(int(get_line())):
        a, b = map(int, get_line().split())
        if a not in g: g[a] = set()
        if b not in g: g[b] = set()
        g[a].add(b)
        g[b].add(a)
 
    segments = deque()
    while g:
        a, queue = g.popitem()
        segment = { a }
        segments.append(segment)
        while queue:
            a = queue.pop()
            if a not in segment:
                segment.add(a)
                queue.update(g[a])
                g.pop(a)
 
    return segments
 
for _ in range(k):
    for segment in read_map():
        outs.append(segment)
        index = len(outs) - 1
        for v in segment:
            outs[v].add(index)
 
queue = deque([1])
visited = set()
distance = [-1] * len(outs)
distance[1] = 0
 
while queue:
    v = queue.pop()
    if v in visited: continue
    
    visited.add(v)
    push = queue.append if v > n else queue.appendleft
    new_cost = distance[v] + (v <= n)
 
    for w in outs[v]:
        # if (eki, eni) not in visited:
        cost = distance[w]
        if cost == -1 or cost > new_cost: 
            distance[w] = new_cost
            push(w)
 
print(distance[n])
2
Эксперт Python
 Аватар для Red white socks
4523 / 1899 / 336
Регистрация: 18.01.2021
Сообщений: 3,489
13.03.2023, 20:00
Цитата Сообщение от DarkShaddow Посмотреть сообщение
Видимо не успею её сдать до 18:00.
Надо было сказать, что сроки поджимают)
Я тогда явовский код скинул бы.
0
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
13.03.2023, 22:22  [ТС]
ну, теперь могу решать в свое удовольствие ни с кем не соревнуясь)))
1
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
14.03.2023, 11:17  [ТС]
rRczZZ, все тесты прошли, спасибо. Вот только не пойму, где в моем коде ошибка (тот что я последний кидал). Ну, ладно пойду разбираться.
0
814 / 422 / 169
Регистрация: 08.02.2013
Сообщений: 711
14.03.2023, 12:24
DarkShaddow, ну я вот пока на informatics.msk тестирую своё решение, python (мой, который выше) проходит там по памяти и времени все тесты и валится на двух простых (5ом и 6ом) с неправильным ответом.. идея такая:
  • создаём карту с номером 0 с N вершинами (1..N), не связанными между собой, загрузка этой карты стоит 0 рублей, остальных - 1 рубль
  • читаем карты 1..k,
    • ищем компоненты связности внутри карты
    • добавляем вместо каждой компоненты в граф новую вершину j
    • добавляем для каждого здания i в компоненте рёбра i → j (загрузка текущей карты из нулевой за 1 рубль) и j → i (загрузка нулевой карты из текущей за 0 рублей). вершина i соответсвует дому из нулевой карты
  • получили граф с N+S (S - число компонент связности по всем картам) вершинами и 2S рёбрами, веса у рёбер i → j равны единице если i <= n (т.е. дом в нулевой карте), остальные - 0, т.е вес не нужно хранить.
  • далее простой поиск в ширину из вершины 1 в N с двусторонней очередью и эвристикой "сначала идём по рёбрам с весом 0"
накидал ночью на c++ аналогичный код, он с запасом проходит по времени и памяти большие тесты и также валится с WA на 5 и 6:
с++, валится на 5 и 6 с WA
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <deque>
#include <unordered_set>
#include <unordered_map>
 
using namespace std;
 
// неправильное решение
 
struct node_t
{
    unordered_set<int> heads; // можно заменить на vector
    bool visited = false;
    int distance = -1;
};
 
using graph_t = unordered_map<int, node_t>;
 
inline graph_t read_map(istream& input, int n)
{
    int r; input >> r;
    unordered_map<int, node_t> graph(n + 1);
    while (r--)
    {
        int a, b; input >> a >> b;
        if (graph.find(a) == graph.end()) graph[a] = {};
        if (graph.find(b) == graph.end()) graph[b] = {};
        graph[a].heads.insert(b);
        graph[b].heads.insert(a);
    }
    return graph;
}
 
inline vector<int> take_segment(graph_t& graph)
{
    queue<int> queue;
    vector<int> segment;
    queue.push(graph.begin()->first);
    while (queue.size())
    {
        int key = queue.front();
        queue.pop();
        
        if (graph.find(key) == graph.end()) continue;
        node_t& node = graph[key];
        segment.push_back(key);
 
        for (auto& head : node.heads)
            queue.push(head);
 
        graph.erase(key);
    }
    return segment;
}
 
inline void insert_segment(vector<node_t>& nodes, vector<int>& segment, int n)
{
    if (!segment.size()) return;
    int index = nodes.size();
    nodes.push_back(node_t{});
    node_t& node = nodes[index];
    for (auto key : segment)
    {
        node.heads.insert(key);
        nodes[key].heads.insert(index);
    }
}
 
inline void fill_distances(vector<node_t>& nodes, int n)
{
    nodes[1].distance = 0;
 
    deque<int> queue;
    queue.push_back(1);
 
    while (queue.size())
    {
        int key = queue.front();
        queue.pop_front();
 
        node_t& node = nodes[key];
        if (node.visited) continue;
        node.visited = true;
 
        int new_distance = node.distance;
        bool map_changed = key <= n;
        if (map_changed) new_distance += 1;
        
        for (auto head_key : node.heads)
        {
            node_t& head = nodes[head_key];
            if (head.visited) continue;
            if (head.distance != -1 && head.distance < new_distance) 
                continue;
 
            head.distance = new_distance;
            if (head_key == n) return;
            if (map_changed) queue.push_back(head_key);
            else queue.push_front(head_key);
        }
    }
}
 
int solve(istream& input)
{
    int n, k; input >> n >> k;
    if (n == 1) return 0;
 
    vector<node_t> nodes(n+1);
 
    while (k--)
    {
        auto graph = read_map(input, n);
        while (graph.size())
        {
            auto segment = take_segment(graph);
            insert_segment(nodes, segment, n);
        }
    }
 
    fill_distances(nodes, n);
    return nodes[n].distance;
}
 
int main()
{
    istream& stream = cin;
    //ifstream stream{"p:\\input.txt"};
    cout << solve(stream);
    return 0;
}

Тогда я убрал поиск компонент связности и закинул все дома со всех карт в граф как вершины, единица только у рёбер из нулевой карты (сток в нулевую карту есть у всех вершин во всех картах). Как и ожидалось - он не проходит по памяти большие тесты (10 и 13, жрёт больше 12 mb), но! 5 и 6 проходит, 300kb 3 ms.
с++, правильное решение, валится на 10 и 13 по памяти
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <deque>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <utility>
 
// правильное решение
 
using namespace std;
 
int offset = 10000;
inline int makepair(int k, int b)
{
    return k * offset + b;
}
 
int main()
{
    //ifstream input{"input.txt"};
    istream& input = cin;
 
    int n, k; input >> n >> k;
    unordered_map<int, unordered_set<int>> outs;
    unordered_map<int, int> distance;
    unordered_set<int> visited;
 
    for (int i = 1; i <= n; i++)
    {
        int v = makepair(0, i);
        outs[v] = unordered_set<int>{};
        distance[v] = -1;
    }
 
    for (int ki = 1; ki <= k; ki++)
    {
        int r; input >> r;
        for (int i = 1; i <= r; i++)
        {
            int a0, b0; input >> a0 >> b0;
            int ai = makepair(ki, a0);
            int bi = makepair(ki, b0);
 
            distance[ai] = -1;
            distance[bi] = -1;
 
            outs[ai].insert(bi);
            outs[bi].insert(ai);
 
            outs[a0].insert(ai);
            outs[b0].insert(bi);
 
            outs[ai].insert(a0);
            outs[bi].insert(b0);
        }
    }
 
    distance[1] = 0;
    deque<int> queue;
    queue.push_back(1);
 
    while (queue.size() > 0)
    {
        int v = queue.front();
        queue.pop_front();
 
        if (visited.find(v) != visited.end()) continue;
        visited.insert(v);
 
        bool map_changed = v < offset;
        int new_cost = distance[v];
        if (map_changed) new_cost += 1;
 
        for (auto w : outs[v])
        {
            int cost = distance[w];
            if (cost == -1 || new_cost < cost)
            {
                distance[w] = new_cost;
                if (map_changed)
                {
                    queue.push_back(w);
                }
                else
                {
                    queue.push_front(w);
                }
            }
        }
    }
 
    cout << distance[n];
    return 0;
}

Собственно, я написал генератор тестов, и он всё утро ищет тест где первое решение не совпадает со вторым.. пока не нашел. Так что, Ваше решение я еще не особо смотрел (своего то нет), + там же, вроде, Red white socks помогает, но я закинул его на informatics и оно валится по памяти на 15 из 20 тестах, могу предположить, что Вы не победили проблему с квадратичной памятью (её можно решить добавлением промежуточных вершин, нулевой карты в моём случае), о которой я писал выше (с картинкой), но это не точно.
2
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
15.03.2023, 10:07  [ТС]
rRczZZ, понял, но я тестировал не на информатикс, а на яндекс.контест. Там у меня ваше решение на python прошло)
0
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
15.03.2023, 10:11  [ТС]
все 19 тестов
Миниатюры
Сталкер (не проходит по памяти)  
1
814 / 422 / 169
Регистрация: 08.02.2013
Сообщений: 711
16.03.2023, 01:55
Лучший ответ Сообщение было отмечено DarkShaddow как решение

Решение

Победил informatics. В 5 и 6 тестах приходят рёбра в вершины не из отрезка [1,N]. Путей, влияющих на ответ, по ним нет. При чтении карты можно сразу выкидывать такие вершины, и решение проходит все тесты.

Цитата Сообщение от DarkShaddow Посмотреть сообщение
Вот только не пойму, где в моем коде ошибка (тот что я последний кидал)
Код даёт правильное решение, несколько что избыточный, например:
  • В первом цикле прогоняется bfs по "загруженным картам" (т.е. бесплатные переходы), используется очередь queue, и в queue_2 закидываются дома, из которых можно перейти в другие карты за один рубль. Соответственно, queue_2 должен быть не очередью, а реализовывать логику множества из номеров домов. Тогда в 50ой строке не будет добавляться 100500 дубликатов
  • Каждая итерация внешнего цикла влечет увеличение стоимости на рубль, о чем говорит count_cost. Значит не обязательно хранить для каждой вершины длину пути до неё от первой. Внутри цикла с bfs, когда достаём вершину из очереди, можно проверять что она равна N, и сразу печатать ответ, выходя из программы. Соотв. viseted - должен реализовывать логику множества, а не массива с длинами. Убирается поиск минимума в 55-57 строках.
  • end_maps не нужен. см. предыдущий пункт
  • start_maps не нужен, это начальное состояние queue. Достаточно при чтении графа из файла сразу закидывать вершины в queue .
В любом случае, я пробовал исправить струтуры, чтобы всё это влезло в 130mb, но bfs в алгоритме пробегает несколько карт одновременно, и всё равно память раздувается. Так что оно того не стоит. Т.е. первое Ваше решение, где отдельно bfs'ите каждую карту на компоненты связности, формируете из них новый маленький граф и потом его еще раз bfs'ите (кстати, можно одну и туже функцию использовать), ближе к теме. Почистить его, убрать рекурсии всякие, и, возможно, пройдет тесты.

Добавлено через 10 минут
Только заметил, что ограничение по памяти 256mb. А я тестировал на informatics к 130mb. Тогда, в целом, можно последний код подогнать. В первую очередь нужно убрать set'ы, они очень много жрут, и словари там гдеони не нужны. Но т.к. я не могу тестировать на яндексе, то не буду выкладывать тут код. Фишка в том, что исправленная версия проходит на informatics 18 из 20 тестов, и в худшем случае, по моим замерам (которые не точные скорее всего) ест 170 mb.
3
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
16.03.2023, 09:02  [ТС]
rRczZZ, спасибо вам за помощь! Учту ваши советы и попробую переделать
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.03.2023, 09:02
Помогаю со студенческими работами здесь

FreeZoneMods на Лазарусе в Онлайн Сталкер ЧН
Здравствуйте! Обращаюсь за помощью к знатокам Lazarus`а 32 бит. Я в программировании ноль. Прошу помочь дописать код контрольной панели...

Не запускается игра Сталкер Чистое небо
привет всем у мя такая проблема -установил сталкер на стандартный путь но при запуске с иконки появляется сообщение что файлwrap_oal.dll...

Долгие загрузки в Сталкер: Зов Припяти
Всем привет! Как-то скачал игру &quot;Зов Припяти&quot;(пиратка естественно), решил поиграть, но удивило вот что: очень, ооочень долгая загрузка, а...

Апгрейд для игры в Warfase, Сталкер.
Хочу заменить материнку скорее всего потому что стоит 1 ядро...очень медленно в играх. Вот характеристики: Intel Pentium 4...

Сумасшедший сталкер в Stalker: Тень Чернобыля
Не далеко от базы Свободы нашёл Сумашедшего сталкера из Свободы, группа его бандит, а выглядел как наёмник, я его убил и у него была...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
37
Ответ Создать тему
Новые блоги и статьи
Отправка уведомления на почту при изменении наименования справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере изменения наименования типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
SDL3 для Desktop (MinGW): Вывод текста со шрифтом TTF с помощью библиотеки SDL3_ttf на Си и C++
8Observer8 24.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-text-sdl3-c. zip finish-text-sdl3-cpp. zip
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
Контроль уникальности заводского номера
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере нетипового документа выдачи шин для спецтехники с табличной частью, разработанного в конфигурации КА2. Номеклатура. . .
Хочу заставить корпорации вкладываться в здоровье сотрудников: делаю мат модель здравосохранения
anaschu 22.03.2026
e7EYtONaj8Y Z4Tv2zpXVVo https:/ / github. com/ shumilovas/ med2. git
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru