#c_sharp #алгоритм
Задача(у меня не совсем такая, она на другом языке, так что я просто привожу подобную).
Даны n заявок на проведение занятий в некоторой аудитории. В каждой заявке указаны
начало и конец занятия si и fi для i-й заявки). В случае пересечения заявок можно удовлетворить
лишь одну из них. Заявки с номерами i и j совместны, если интервалы (si,fi) и (sj,fj)
не пересекаются (то есть fi < fj или fj < fi). Задача о выборе заявок состоит в том,
чтобы набрать максимальное количество совместных друг с другом заявок.
Количество заявок и сами заявки в текстовом документе prednasky.in, то-есть:
Ввод (текстовый документ):
5 - первая строчка - кол-во интервалов
2 4 (2 - начало интервала, 4 - конец и тд)
1 7
6 9
9 11
5 8
Вывод:
3 (максимальное количество совместных друг с другом заявок)
1 5 4 (номера этих заявок(если есть несколько вариантов - выписать любой))
Программу проверяет специальный сайт с тестами, и моя программа не проходит тесты
на больших числах, хотя, как мне кажется я добился временной сложности nlogn+n (с памятью
всё уже нормально, именно по скорости не проходит). Вот сам код:
class Program
{
static int N;
static int[,] a;
static void Main(string[] args)
{
using (StreamReader sr = new StreamReader(@"prednasky.in"))
{
string line;
line = sr.ReadLine();
N = int.Parse(line);
a = new int[N, 2];
int[] indx = new int[N];
int[] b = new int[N];
for (int i = 0; i < N; i++)
{
line = sr.ReadLine();
int[] nums = line.Trim().Split().Select(w => int.Parse(w)).ToArray();
//начало интервалов и их идексы записываем в массив А
a[i, 0] = nums[0];
a[i, 1] = i + 1;
//Концы интервалов записываем в массив б
b[i] = nums[1];
//заполняем массив индексов;
indx[i] = i;
}
//Cортировка массива индексов по массиву б
Array.Sort(b, indx);
//Дальше одним циклом проходим массив а, но не по i, а по полю индексов
(для того, что бы не сортировать двумерный массив, геморно же, лучше одномерный))
//string str = "";
int last = 0;
int poc = 0;
for (int i = 0; i < N; i++)
{
if (a[indx[i], 0] > last)
{
//в самое начало "отсортированного" массива записываем нужные
числа по порядку
a[indx[poc], 0] = a[indx[i], 1];
poc++;
last = b[i];
}
}
using (StreamWriter sr1 = new StreamWriter(@"rozvrh.out"))
{
sr1.WriteLine(poc);
for (int i = 0; i < poc; i++)
{
sr1.Write(a[indx[i], 0]);
sr1.Write(" ");
}
}
}
}
}
Алгоритм работает, проблема только со скоростью. Любым идеям буду рад)
Ответы
Ответ 1
Можно отбирать среди оставшихся допустимых заявок ту, у которой время окончания наименьшее. В этом случае мы ничего не теряем. Кроме того, следует удалять из очереди заявки, которые не могут быть использованы. Алгоритм может быть рекурсивным, если вызываемая процедура получает допустимое начало интервала $start, очередь из оставшихся заявок $queue и массив принятых заявок $request. Программа на PHP: $request = [1=>[2,4], [1,7], [6,9], [9,11], [5,8]]; // starting shedule function print_1d($text, $arr){ echo "$text"; foreach($arr as $value) printf("%2d ", $value); } function print_sh($text, $arr){ echo "$text"; foreach ($arr as $key => $value) { if(gettype($value) == "array") print_1d(" $key=> ", $value); else echo " $key=>$value"; } } function greedy($sh){ global $request, $counter; $counter++; print_sh("
sh ", $sh); $start = $sh['start']; $queue = $sh['queue']; $accepted = $sh['accepted']; if(empty($queue)) return $sh; foreach ($queue as $key=>$number) { if($request[$number][0] < $start) unset($queue[$key]); elseif(!isset($finish) || ($request[$number][1] < $finish)) { $finish = $request[$number][1]; $keynext = $key; } } $start = $finish + 1; unset($queue[$keynext]); $accepted[] = $keynext+1; // then test the variant return greedy(['start'=>$start, 'queue'=>$queue, 'accepted'=>$accepted]); // when the request is accepted } $n = count($request); $counter = 0; print_sh("The requests are:
",$request); $shedule = [ 'start' => 0, 'queue' => range(1, $n), 'accepted'=>[] ]; echo "
The local optima are:
"; $shedule_opt = greedy($shedule); print_sh("
Taking in account $counter variants.
The optimal variant is:
", $shedule_opt); Результаты: The requests are: 1=> 2 4 2=> 1 7 3=> 6 9 4=> 9 11 5=> 5 8 The local optima are: sh start=>0 queue=> 1 2 3 4 5 accepted=> sh start=>5 queue=> 2 3 4 5 accepted=> 1 sh start=>9 queue=> 3 4 accepted=> 1 5 sh start=>12 queue=> accepted=> 1 5 4 Taking in account 4 variants. The optimal variant is: start=>12 queue=> accepted=> 1 5 4
Комментариев нет:
Отправить комментарий