Считайте Запрос. Сформируйте NameValueCollection и обработайте Вашу логику соответственно:
NameValueCollection nvc = Request.Form;
string userName, password;
if (!string.IsNullOrEmpty(nvc["txtUserName"]))
{
userName = nvc["txtUserName"];
}
if (!string.IsNullOrEmpty(nvc["txtPassword"]))
{
password = nvc["txtPassword"];
}
//Process login
CheckLogin(userName, password);
..., где "txtUserName" и "txtPassword" Имена из средств управления на странице регистрации.
Выбор подматриц для покрытия запрошенных значений является формой задачи покрытия набора и, следовательно, NP-завершенной. Ваша проблема добавляет к этой и без того сложной проблеме то, что стоимость наборов различается.
То, что вы позволяете переставлять строки и столбцы, не является такой большой проблемой, потому что вы можете просто рассматривать несвязанные подматрицы. Строка один, столбцы с четвертого по седьмой и строка пять, столбцы четыре, два, семь являются допустимым набором, потому что вы можете просто поменять местами строку два и строку пять и получить связанную подматрицу строку один, столбец четыре и строку два, столбец семь. Конечно, это добавит некоторые ограничения - не все наборы действительны для всех перестановок - но я не думаю, что это самая большая проблема.
В статье в Википедии приводятся результаты о несовместимости, заключающиеся в том, что задача не может быть решена за полиномиальное время лучше, чем с коэффициентом 0,5 * log2 (n)
, где n
- количество наборов. В вашем случае 2 ^ (n * p)
является (довольно пессимистичным) верхним пределом для количества наборов и выходов, решение которого можно найти только с коэффициентом 0,5 * n * p
за полиномиальное время (помимо N = NP и игнорирования переменных затрат).
Оптимистическая нижняя граница для количества наборов, игнорирующих перестановки строк и столбцов, составляет 0,5 * n ^ 2 * p ^ 2
дает гораздо лучший коэффициент log2 (n) + log2 (p) - 0,5
. Следовательно, вы можете рассчитывать найти решение только в худшем случае n = 1000
и p = 200
с коэффициентом примерно 17
в оптимистическом случай и с коэффициентом примерно 100000
в пессимистическом случае (все еще игнорируя различные затраты).
Таким образом, лучшее, что вы можете сделать, - это использовать эвристический алгоритм (статья в Википедии упоминает почти оптимальный жадный алгоритм) и согласитесь, что будет случай, когда алгоритм будет работать (очень) плохо. Или вы идете другим путем, используете алгоритм оптимизации и пытаетесь найти хорошее решение, тратя больше времени. В этом случае я бы предложил попробовать использовать A * search .
000 в пессимистическом случае (все еще игнорируя различные затраты).Итак, лучшее, что вы можете сделать, - это использовать эвристический алгоритм (статья в Википедии упоминает почти оптимальный жадный алгоритм) и согласиться с тем, что будет случай, когда алгоритм работает (очень) плохо. Или вы идете другим путем, используете алгоритм оптимизации и пытаетесь найти хорошее решение, используя больше времени. В этом случае я бы предложил попробовать использовать A * search .
000 в пессимистическом случае (все еще игнорируя различные затраты).Лучшее, что вы можете сделать, - это использовать эвристический алгоритм (статья в Википедии упоминает почти оптимальный жадный алгоритм) и согласиться с тем, что будет случай, когда алгоритм работает (очень) плохо. Или вы идете другим путем, используете алгоритм оптимизации и пытаетесь найти хорошее решение, тратя больше времени. В этом случае я бы предложил попробовать использовать A * search .
Хорошо, мое понимание вопроса изменилось. Новые идеи:
Храните каждую строку как длинную битовую строку. И пары битовых строк вместе, пытаясь найти пары, которые максимизируют количество 1 бит. Разрастите эти пары в большие группы (отсортируйте и попытайтесь сопоставить действительно большие группы друг с другом). Затем создайте запрос, который попадет в самую большую группу, а затем забудьте обо всех этих битах. Повторяйте, пока все не будет сделано. Может быть, иногда переключаться со строк на столбцы.
Ищите все строки / столбцы с нулевым или небольшим количеством точек в них. «Удалите» их временно. Теперь вы смотрите на то, что может быть покрыто запросом, который их не учитывает. Теперь, возможно, примените один из других методов, а потом разберетесь с проигнорированными строками / столбцами. Другой способ подумать об этом: сначала разберитесь с более плотными точками, а затем переходите к более разреженным.
Поскольку ваши значения скудны, может ли случиться так, что многие пользователи запрашивают похожие значения? Возможно ли кеширование в вашем приложении? Запросы можно индексировать с помощью хэша, который является функцией позиции (x, y), чтобы вы могли легко идентифицировать кэшированные наборы, которые попадают в правильную область сетки. Хранение кэшированных наборов в дереве, например, позволит вам очень быстро найти минимальные кэшированные подмножества, которые охватывают диапазон запросов. Затем вы можете выполнить линейный поиск по небольшому подмножеству.
Я бы рассмотрел n записей (строк) и p полей (столбцов), упомянутых в запросе пользователя, установленным как n точек в p-мерном пространстве ({0,1} ^ p) с i-я координата равна 1, если у нее есть X, и идентифицируют иерархию кластеров , с самым грубым кластером в корне, включая все X. Для каждого узла в иерархии кластеризации рассмотрите продукт, который охватывает все необходимые столбцы (это строки (любой подузел) x столбцы (любой подузел)). Затем решите снизу вверх, объединять ли дочерние покрытия (оплачивая все покрытие) или оставить их как отдельные запросы. (покрытия сделаны не из смежных столбцов, а именно из тех, которые необходимы; например, подумайте о битовом векторе)
Я согласен с Артелиусом, что перекрывающиеся запросы продуктов могут быть дешевле;
Я уверен, что где-то есть действительно хороший алгоритм для этого, но вот мои собственные интуитивные идеи:
Подход «бросай прямоугольники»:
Рост
Сжатие
Quad
Также: имейте в виду , что иногда будет лучше иметь два перекрывающихся прямоугольника, чем один большой прямоугольник, который является их надмножеством. Например, в случае, когда два прямоугольника просто перекрываются в одном углу.
Quad
Также: имейте в виду , что иногда будет лучше иметь два перекрывающихся прямоугольника, чем один большой прямоугольник, который является их надмножеством. Например, в случае, когда два прямоугольника просто перекрываются в одном углу.
Quad
Также: имейте в виду , что иногда будет лучше иметь два перекрывающихся прямоугольника, чем один большой прямоугольник, который является их надмножеством. Например, в случае, когда два прямоугольника просто перекрываются в одном углу.
Quad
Также: имейте в виду , что иногда будет лучше иметь два перекрывающихся прямоугольника, чем один большой прямоугольник, который является их надмножеством. Например, в случае, когда два прямоугольника просто перекрываются в одном углу.
Quad
Также: имейте в виду , что иногда будет лучше иметь два перекрывающихся прямоугольника, чем один большой прямоугольник, который является их надмножеством. Например, в случае, когда два прямоугольника просто перекрываются в одном углу.
имейте в виду , что иногда будет лучше иметь два перекрывающихся прямоугольника, чем один большой прямоугольник, который является их надмножеством. Например, в случае, когда два прямоугольника просто перекрываются в одном углу. имейте в виду , что иногда будет лучше иметь два перекрывающихся прямоугольника, чем один большой прямоугольник, который является их надмножеством. Например, в случае, когда два прямоугольника просто перекрываются в одном углу.Я немного поработал над этим, и вот очевидный, O (n ^ 3) жадный алгоритм нарушения симметрии (записи и поля обрабатываются отдельно) в псевдо- code.
Идея тривиальна: мы начинаем с проверки одного запроса на запись и выполняем наиболее подходящее слияние, пока не останется ничего, достойного слияния. У этого алгоритма есть очевидный недостаток, заключающийся в том, что он не позволяет перекрывать запросы, но я ожидаю, что он будет работать достаточно хорошо в реальном случае (с a + n * (p ^ b) + c * n * p * (1 - g)
функция стоимости):
# given are # a function cost request -> positive real # a merge function that takes two pairs of sets (f1, r1) and (f2, r2) # and returns ((f1 U f2), (r1 U r2)) # initialize with a request per record requests = [({record},{field if (record, field) is needed}) for all needed records] costs = [cost(request) for request in requests] finished = False while not finished: # there might be something to gain maximum_gain = 0 finished = True this_step_merge = empty # loop onto all pairs of request for all (request1, request2) in (requests x request) such as request1 != request2: merged_request = merge(request1, request2) gain = cost(request1) + cost(request2) - cost(merged_request) if gain > maximum_gain: maximum_gain = gain this_step_merge = (request1, request2, merged_request) # if we found at least something to merge, we should continue if maximum_gain > 0: # so update the list of requests... request1, request2, merged_request = this_step_merge delete request1 from requests delete request2 from requests # ... and we are not done yet insert merged_request into requests finished = False output requests
Это O (n3 * p), потому что:
n
запрашивает , а
цикл удаляет ровно один запрос из пула на каждой итерации. внутренний цикл for
выполняет итерацию по ( ni ^ 2 - ni
) / 2 различных парах запросов, причем ni изменяется от n до единицы в худшем случае (когда мы объединить все в одну большую просьбу).
Заранее благодарим!