Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.03.2010, 19:32   #1
Sheril
 
Регистрация: 20.03.2010
Сообщений: 6
Вопрос Разрезы без отходов

Есть такая задача:
Разрезать прямоугольник размера X*Y на детали прямоугольной формы размера X1*Y1 и X2*Y2, чтобы отходы были минимальны. Возможны только вертикальные и горизонтальные разрезы. Т.е. после первого разреза получается два прямоугольника, которые в последствии также можно разрезать.
Входные данные
Входные данные находятся в текстовом файле с именем input.txt:
Во входном файле шесть целых чисел (1<=X<=100, 1<=Y<=100, 1<=X1<=X, 1<=Y1<=Y, 1<=X2<=X, 1<=Y2<=Y).

Выходные данные

Выходные данные должны быть записаны в текстовый файл с именем output.txt и иметь следующий формат:
единственное целое число равное минимальной сумме остатков.
Пример входных данных

10
10
2
9
3
4
Пример выходных данных
10

Подскажите, как написать максимально быстрый алгоритм?
Sheril вне форума Ответить с цитированием
Старый 20.03.2010, 23:38   #2
Carbon
JAVA BEAN
Участник клуба
 
Аватар для Carbon
 
Регистрация: 22.04.2007
Сообщений: 1,329
По умолчанию

Куски на 90 градусов вращать можно?
Carbon вне форума Ответить с цитированием
Старый 21.03.2010, 09:00   #3
Sheril
 
Регистрация: 20.03.2010
Сообщений: 6
По умолчанию

Да, детали вращать можно. И разрезы от края до края. Зигзагообразно резать нельзя. Эта задача как-то сводится к задаче о разрезке обоев с рисунком. Но как решать задачу про обои я знаю лишь в теории.
Sheril вне форума Ответить с цитированием
Старый 21.03.2010, 09:27   #4
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,713
По умолчанию

1- решение данной задачи представляет коммерческую ценность и немалую
2- существуют различные приближающие методы: генетические алгоритмы, симплекс-метод, параметрическая оптимизация, исключения интервалов и т.п. (это все есть в вики)
3- на форуме >>> обсуждалось <<<

тут очень хорошо расписан генетический алгоритм + прилагаю статью об еще одном методе фигурного раскроя (см. ниже)
Вложения
Тип файла: pdf статья_алгоритм расчета фигурного раскроя.pdf (176.4 Кб, 31 просмотров)
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 21.03.2010, 10:16   #5
Carbon
JAVA BEAN
Участник клуба
 
Аватар для Carbon
 
Регистрация: 22.04.2007
Сообщений: 1,329
По умолчанию

Цитата:
Сообщение от raxp Посмотреть сообщение
1- решение данной задачи представляет коммерческую ценность и немалую
2- существуют различные приближающие методы: генетические алгоритмы, симплекс-метод, параметрическая оптимизация, исключения интервалов и т.п. (это все есть в вики)
3- на форуме >>> обсуждалось <<<

тут очень хорошо расписан генетический алгоритм + прилагаю статью об еще одном методе фигурного раскроя (см. ниже)
Я тя умоляю. Там фигурный раскрой и вырезки наверняка произвольной формы. А тут вырезки всего двух вариантов и то они прямоугольные и раскрой от края до края.

Обычное динамическое программирование:

Код:
#include <stdio.h>


int main( int, char ** )
{

	int X, Y;
	int X1, Y1;
	int X2, Y2;

	scanf( "%d%d%d%d%d%d", &X, &Y, &X1, &Y1, &X2, &Y2 );
	
	int refuse[ 100 ][ 100 ];

	for ( int i = 0; i < X; ++i )
		for ( int j = 0; j < Y; ++j )
		{
			if ( i == X1 - 1 && j == Y1 - 1 ||
				i == Y1 - 1 && j == X1 - 1 ||
				i == X2 - 1 && j == Y2 - 1 ||
				i == Y2 - 1 && j == X2 - 1 )
				refuse[ i ][ j ] = 0;
			else
			{
				refuse[ i ][ j ] = ( i + 1 )*( j + 1 );

				int val = 1;

				for ( int k = 0, k_end = ( i + 1 ) >> 1; k < k_end && val; ++k )
				{
					val = refuse[ k ][ j ] + refuse[ i - 1 - k ][ j ];
					if ( refuse[ i ][ j ] > val ) refuse[ i ][ j ] = val;
				}

				for ( int k = 0, k_end = ( j + 1 ) >> 1; k < k_end && val; ++k )
				{
					val = refuse[ i ][ k ] + refuse[ i ][ j - 1 - k ];
					if ( refuse[ i ][ j ] > val ) refuse[ i ][ j ] = val;
				}
			}
		}

	printf( "%d", refuse[ X - 1 ][ Y - 1 ] );

	getchar();
	getchar();

	return 0;
}

Последний раз редактировалось Carbon; 21.03.2010 в 10:23.
Carbon вне форума Ответить с цитированием
Старый 21.03.2010, 11:44   #6
Sheril
 
Регистрация: 20.03.2010
Сообщений: 6
По умолчанию

Carbon, Спасибо! Она работает очень(!) быстро. Вы сами придумали алгоритм или это уже существующий? Мы такого не учили... Хотелось бы почитать.
Нулями метим углы возможного расположения деталей. А как с помощью побитового сдвига(я надеюсь это он?) и оценок мы заполняем матрицу?
Sheril вне форума Ответить с цитированием
Старый 21.03.2010, 12:09   #7
Carbon
JAVA BEAN
Участник клуба
 
Аватар для Carbon
 
Регистрация: 22.04.2007
Сообщений: 1,329
По умолчанию

Цитата:
Сообщение от Sheril Посмотреть сообщение
Carbon, Спасибо! Она работает очень(!) быстро. Вы сами придумали алгоритм или это уже существующий? Мы такого не учили... Хотелось бы почитать.
Нулями метим углы возможного расположения деталей. А как с помощью побитового сдвига(я надеюсь это он?) и оценок мы заполняем матрицу?
Я ж говорю. Это динамическое программирование.
Ну до этого я догадался сам, хотя подобную задачу видел на одной из школьных олимпиад.

Алгоритм такой:
Расчитываем все остатки при разрезании досок меньших размеров. По очереди рассматриваем все доски и пусть у нас встретилась доска PxQ:

1) Если одна из двух частей имеет размеры PxQ или QxP, то в этом случае остатков не будет и на место ставим 0.
2) В противном случае на место ставим P*Q. Т.е. если в эту часть не влезет ни одна из исходных фигур.
Затем перебираем все возможные разрезы по горизонтали и вертикали до P/2 и Q/2 соответственно (дальше делить нет смысла, потому что значения будут повторяться) и считаем сумму элементов [A;Q] и [P-A;Q] и также [P;B] и [P;Q-B] (это и есть разрезы по координатам A и B) и среди этих сумм находим минимальную сумму остатков.

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

ЗЫ Не забываем нажимать на весы.

Последний раз редактировалось Carbon; 21.03.2010 в 12:13.
Carbon вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
таблица без БД m.a.x.i.m БД в Delphi 6 05.12.2009 15:46
Без антивируса Slavik Безопасность, Шифрование 54 25.05.2009 01:46
Процедуры без Bios и без Dos,бывают? codeok Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 3 31.10.2008 03:17
без VBA ExcArt Microsoft Office Excel 7 18.02.2008 01:23