powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Вопрос о существовании более быстрого алгоритма.
20 сообщений из 20, страница 1 из 1
Вопрос о существовании более быстрого алгоритма.
    #38753215
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте.
Решал сегодня относительно простую задачу, вот она .
Решение в лоб очевидно

Код: plaintext
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.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

struct Point
{
	int x;
	int y;
};

//расстояние между двумя точками в D^2
long double get_distance_between_Points(struct Point* p1, struct Point* p2)
{
	long double dx = p1->x - p2->x;
	long double dy = p1->y - p2->y;
	return sqrt(dx*dx + dy*dy);
}

//вес графа. на входе адрес графа, количество точек, стартовая позиция
long double get_weight_graph(struct Point* p, int num, int s)
{
	long double res = 0;
	for (int i = 0; i < num; ++i)
	{
		res += get_distance_between_Points(p + i, p + s);
	}
	return res;
}

//Попытка провести интернет
bool try_connect_to_WEB(struct Point* p, int num, struct Point* center, long double money, int cast)
{
	long double res;
	int i = 0;
	do
	{
		res = get_weight_graph(p, num, i) + get_distance_between_Points(p + i, center);
		i += 1;
	} while (res*cast > money && i < num);
	return res*cast <= money;
}

int main(int argc, char** argv)
{
	FILE* in = fopen("input.txt", "r");
	if (!in)
	{
		printf("File 'input.txt' not found.\n");
		return 0;
	}
	
	//считываю данные
	int num, cast;
	long double money;
	fscanf(in, "%d %d %lf", &num, &cast, &money);
	struct Point* p = (struct Point*)malloc(sizeof(struct Point)*num);
	for (int i = 0; i < num; ++i)
	{
		fscanf(in, "%i %i", &p[i].x, &p[i].y);
	}
	struct Point center;
	fscanf(in, "%i %i", &center.x, &center.y);
	fclose(in);

	//расчёт
	FILE* out = fopen("output.txt", "w");
	fprintf(out,try_connect_to_WEB(p,num,&center,money,cast)? "YES" : "NO");
	free(p);
	fclose(out);

	return 0;
}



Но если N увеличить например в 100 раз, очевидно, что такое решение не будет подходящим. Как вы считаете, существует ли у этой задачи более быстрое решение ? Мне кажется что нет. Но я в этом не уверен.
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753233
Barlone
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну это же классическая Задача коммивояжёра
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753236
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У тебя есть избыточность при вызове get_distance_between_Points(), т.к. считаешь каждый отрезок дважды. Т.е. проверяя точку А ты считаешь отрезок AB, проверяя точку B считаешь BA.

Операция извлечения корня достаточно тяжелая, поэтому можно сначала посчитать все отрезки в массив, а при расчете просто брать из массива.
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753241
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Простите, вы совершенно точно уверенны что это классическая задача коммивояжёра ?
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753242
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий, согласен, спасибо :) Но это не решает основную проблему
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753244
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryДмитрий, согласен, спасибо :) Но это не решает основную проблему
А какая основная проблема? Ты спросил
SashaMercuryКак вы считаете, существует ли у этой задачи более быстрое решение ?
Я тебе его назвал.
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753425
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нет, алгоритм практически не изменился. Полный перебор
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753453
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryНет, алгоритм практически не изменился. Полный перебор
От перебора ты не уйдешь. В худшем случае он будет полный.

Максимум что можно оптимизировать - это вызывать get_distance_between_Points() один раз вместо двух. Эта функция у тебя достаточно тяжелая, поэтому будет выигрыш по времени.

Сомневаешься - затести оба варианта на большом наборе точек. Сгенери точки генератором случайных чисел и засеки время (функция clock() текущее время в мс).
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753520
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Посмотрел как корень вычисляется, оказывается сопроцессором (думал функция из сишной библиотеки), значит не тяжелая это операция, накладные расходы на организацию массива могут и замедлить расчет. Тестить надо :)
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753546
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это интересно.

То есть всё-таки в худшем случае полный перебор ? Как это можно доказать ?
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753579
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryЭто интересно.

То есть всё-таки в худшем случае полный перебор ? Как это можно доказать ?
Ты же у нас математик, тебе и доказывать :)

Не получив длины всех отрезков нельзя решить (в худшем случае), а чтобы их получить - перебор всех пар точек.
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753627
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я постараюсь узнать как это делается. Недавно в книжном магазине я читал Скиену, и встретил что-то про такие алгоритмы.
Спасибо. Меня гонят, доброго времени суток
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753629
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотел кстати недавно снова зайти почитать, а его уже купили ( полгода не покупали, а тут на тебе и купили
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753652
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercury, Саша а ты пробовал менять long double на double?

Бинарник меняется?
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753716
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BarloneНу это же классическая Задача коммивояжёра
Это не коммивояжер. У автора - кривенькая постановка которая к расчёту
проектов прокладки интернета имеет весьма отдалённое отношение. Расстояние
в километрах вообще редко определяло стоимость подключения. Гораздо важнее
- технология. Количество свободных портов, нагрузка и количество hops, лаги
и прочее.
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753722
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TПосмотрел как корень вычисляется, оказывается сопроцессором (думал функция из сишной библиотеки), значит не тяжелая это операция, накладные расходы на организацию массива могут и замедлить расчет. Тестить надо :)
Он вычисляется средствами библиотеки. Будет ли она использовать FPU или нет - отдельный вопрос.
И я заметил что ценность FPU-вычислений заметно ослаблена в пользу новых наборов команд.
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38753871
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Затестил массив, добавил кэш длин отрезков в код SashaMercury, в дебаге чуть медленнее, в релизе вдвое медленнее
Исходник
Код: sql
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.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

struct Point
{
	int id;
	int x;
	int y;
};

int use_sqrt1 = 0;
//расстояние между двумя точками в D^2
long double get_distance_between_Points(struct Point* p1, struct Point* p2)
{
#ifdef _DEBUG
		use_sqrt1++;
#endif
	long double dx = p1->x - p2->x;
	long double dy = p1->y - p2->y;
	return sqrt(dx*dx + dy*dy);
}

//вес графа. на входе адрес графа, количество точек, стартовая позиция
long double get_weight_graph(struct Point* p, int num, int s)
{
	long double res = 0;
	for (int i = 0; i < num; ++i)
	{
		res += get_distance_between_Points(p + i, p + s);
	}
	return res;
}

//Попытка провести интернет
bool try_connect_to_WEB(struct Point* p, int num, struct Point* center, long double money, int cast)
{
	long double res;
	int i = 0;
	do
	{
		res = get_weight_graph(p, num, i) + get_distance_between_Points(p + i, center);
		i += 1;
	} while (res*cast > money && i < num);
	return res*cast <= money;
}

// ***********************************************************************************************
#define POINT_COUNT 5000
#include <time.h>

long double* cache = NULL;
int use_sqrt2 = 0;
int use_cache = 0;

//расстояние между двумя точками в D^2
long double get_distance_between_Points2(struct Point* p1, struct Point* p2)
{
	long double res = cache[p1->id * POINT_COUNT + p2->id];
	if(res == 0) {
		long double dx = p1->x - p2->x;
		long double dy = p1->y - p2->y;
		res = sqrt(dx*dx + dy*dy);
		cache[p2->id * POINT_COUNT + p1->id] = res;
#ifdef _DEBUG
		use_sqrt2++;
	}  else {
		use_cache++;
#endif
	}
	return res;
}

//вес графа. на входе адрес графа, количество точек, стартовая позиция
long double get_weight_graph2(struct Point* p, int num, int s)
{
	long double res = 0;
	for (int i = 0; i < num; ++i)
	{
		res += get_distance_between_Points2(p + i, p + s);
	}
	return res;
}


bool try_connect_to_WEB2(struct Point* p, int num, struct Point* center, long double money, int cast)
{
	long double res;
	int i = 0;
	do
	{
		res = get_weight_graph2(p, num, i) + get_distance_between_Points(p + i, center);
		i += 1;
	} while (res*cast > money && i < num);
	return res*cast <= money;
}


int main(int argc, char** argv)
{
	srand((int)time(NULL));
	struct Point p[POINT_COUNT];
	int num = POINT_COUNT;
	int cast = 1;
	long double money = POINT_COUNT * 300;
	for(int i = 0; i < POINT_COUNT; i++) {
		p[i].id = i;
		p[i].x = rand() % 1000;
		p[i].y = rand() % 1000;
	}
	struct Point center;
	center.id = POINT_COUNT;
	center.x = rand() % 1000;
	center.y = rand() % 1000;

	// вариант SashaMercury
	clock_t time1 = clock();
	bool res1 = try_connect_to_WEB(p,num,&center,money,cast);

	// вариант кэшем
	clock_t time2 = clock();
	cache = (long double*)calloc(POINT_COUNT * POINT_COUNT, sizeof(long double));
	bool res2 = try_connect_to_WEB2(p,num,&center,money,cast);

	clock_t time3 = clock();
	printf("Res 1 %s time %d  sqrt=%d\n", res1 ? "YES" : "NO", time2 - time1, use_sqrt1);
	printf("Res 2 %s time %d  cache=%d sqrt=%d\n", res2 ? "YES" : "NO", time3 - time2, use_cache, use_sqrt2);

	system("pause");
	return 0;
}


Все-таки быстрее считать корни чем кэшировать.
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38754042
BagaBaga
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Немного странная задача.

На первый взгляд можно свести к задаче нахождения минимального остовного дерева в неорграфе.

Но! С учётом ограничения
авторДля того чтобы подключиться к сети всем N поросятам необходимо:
1. провести провод от точки подключения до домика одного из поросят;
2. от подключенного поросенка провести провода ко всем остальным.

алгоритм Прима или крускала придётся модифицировать, чтобы не рассматривал "лишние" рёбра ...
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38754151
nevidomy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Примы и остовые деревья тут ни при чем. И это далеко не комивояжер.
Да и вообще решения основанные на графовых алгоритмах вряд ли помогут (колличество ребер в графе в данном случае O(n^2), так как это полный граф).
Скорее всего это задача на модификацию поиска геометрической медианы.
Вики:
http://en.wikipedia.org/wiki/Geometric_median
Конечно же в евклидовой метрике и в данном случае в 2D.

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

На практике же я бы решал эту задачу методом "имитации отжига" http://en.wikipedia.org/wiki/Simulated_annealing .
Он само собой являеться недетерминированным алгоритмом, но чаще всего получает AC на подобных задач. Как альтернатива, могу еще порекомендовать A* или генетические алгоритмы, на практике генетика будет хуже отжига, чисто мое опытное мнение.

Вообще задача (общая) намного проще решаеться для манхеттенской метрики, ну и как "не самое очевидное следствие" для суммы квадратов расстояний, подробности можно найти вот тут: http://stackoverflow.com/questions/12934213/how-to-find-out-geometric-median .
...
Рейтинг: 0 / 0
Вопрос о существовании более быстрого алгоритма.
    #38754152
nevidomy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
nevidomy,
omg... с тегами не разобрался :)
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Вопрос о существовании более быстрого алгоритма.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]