Привет, мне нужна помощь со следующим сценарием в php. У меня есть база данных с пользователями, у каждого пользователя есть идентификатор, have_card и want_card. Я знаю, как добиться прямого совпадения (один пользователь торгует с другим пользователем). Но если прямого совпадения нет, но есть круговая замена, например:
У пользователя №1 есть карточка A, она хочет карточку B
У пользователя № 2 есть карточка B, она хочет карточку C
У пользователя №3 есть карточка C, она хочет карточку A
В этом сценарии нет прямого совпадения между двумя пользователями. Но если:
Пользователь №1 передает свою карту пользователю №3.
Пользователь №3 передает свою карточку пользователю №2.
Пользователь №2 передает свою карту пользователю №1.
Все счастливы.
Все, с чего мне нужно начать, - это Пользователь №1. Как мне найти Пользователя №2 и Пользователя №3?
Спасибо всем за ответы.






Вот как я бы это сделал: Создайте рекурсивный алгоритм, подобный этому:
1 беру одного пользователя, смотри, что он хочет
2 найти другого пользователя, у которого есть то, что нужно
- if user two wants, what user one has, everything is fine an we're done
- if not, continue
3 найдите другого пользователя, у которого есть то, что хочет пользователь два
- if user three wants, what user one has, everything is fine and we're done
- if not, continue ...
... и так далее, но у вас должно быть ограничение для рекурсивных уровней, чтобы предотвратить бесконечный поиск.
Может быть, это:
Поиск возможных первых совпадений (пользователи, у которых есть карта, которую хочет пользователь №1)
select name from user where has in (select wants from user where name = '1');
Просмотрите эти совпадения и попробуйте найти недостающее звено:
select name from user where name in (select name from user where has in (select wants from user where name = <match>));
Это сложный сценарий. Некоторое время назад мне пришлось создать это приложение для обмена книгами, и, используя белую доску, мне было легче визуализировать и решить проблему.
Я использовал одну и ту же таблицу внутри запроса несколько раз, просто используя другое имя.
В моем сценарии необходимые книги находились в отдельной таблице от книг, которые были у пользователей. Надеюсь, вы сможете увидеть логику этого запроса:
$query = "SELECT
A.Owner_ID as Owner_1, C.Owner_ID as Owner_2, E.Owner_ID as Owner_3
FROM
E_User_Books_Have as A, E_User_Books_Have as C, E_User_Books_Have as E,
E_User_Books_Needed as B, E_User_Books_Needed as D,E_User_Books_Needed as F
WHERE
A.Book_ID=D.Book_ID AND
C.Book_ID=F.Book_ID AND
E.Book_ID=B.Book_ID AND
A.Owner_ID='$ME' AND B.Owner_ID='$ME' AND A.ID='$ID'AND
C.Owner_ID=D.Owner_ID AND
E.Owner_ID=F.Owner_ID AND
C.Owner_ID!='$ME' AND
E.Owner_ID!='$ME'";
Интересно, что я наткнулся на похожую вещь с Настольная ИграГиковская Математика Торговля. По сути, каждый указывает, что он либо хочет игру, либо имеет игру, и алгоритм максимизирует сделки, включая циклические зависимости.
Это именно то, что вам нужно.
Вот объяснение того, как работает TradeMaximizer. Он использует Алгоритм Дейкстры и косые кучи для поиска минимальных подходящих решений (т.е. меньший круг предпочтительнее большего круга).
Конечно, это создано на Java, но алгоритмы универсальны, и вы можете воссоздать их по мере необходимости, особенно если вы понимаете, что он делает и почему.
+1 за использование теории графов (в отличие от других хакерских предложений).