Php 寻找所有可能的交换卡的方法
我正在开发一个PHP应用程序,它可以找到所有可能的交换卡的方法。每个用户至少有一张卡。当用户请求一张卡时,应用程序会向他显示所有可能的方法,以交换他所请求的卡 让我们说:Php 寻找所有可能的交换卡的方法,php,algorithm,Php,Algorithm,我正在开发一个PHP应用程序,它可以找到所有可能的交换卡的方法。每个用户至少有一张卡。当用户请求一张卡时,应用程序会向他显示所有可能的方法,以交换他所请求的卡 让我们说: user 1 has card type A user 2 has card type B user 3 has card type C 让我们假设: user 1 wants card type C user 2 wants card type A user 3 wants card type B 如果用户1请求卡C
user 1 has card type A
user 2 has card type B
user 3 has card type C
让我们假设:
user 1 wants card type C
user 2 wants card type A
user 3 wants card type B
如果用户1请求卡C,唯一的解决方案是:
user 1 gives user 2 his card
user 2 gives user 3 his card
user 3 gives user 1 his card
但如果还有另外两个用户呢:
user 4 has card type B & wants card type A
user 5 has card type C & wants card type B
现在,如果用户1请求卡C,除了上面的解决方案外,还有一个解决方案:
user 1 gives user 4 his card
user 4 gives user 5 his card
user 5 gives user 1 his card
用户可以拥有或请求的卡数没有限制。到目前为止,我创建了两个SQL表。表“cards”记录每个用户ID和cardID。“requests”表跟踪每个用户ID和所需的cardID 我不会使用纯PHP来实现这一点。我更愿意创建一个MySQL表,为每个用户存储一条记录,记录该用户拥有的卡以及他想要的卡。然后,我会运行这样的程序:
$sql = "SELECT * FROM users";
$result = $this->db->query();
$users = $result->getAll(); //A list of all the users.
foreach ($users as $user)
{
$sql = "SELECT * FROM users WHERE cardId = '$user->wantedCardId'";
$result = $this->db->query($sql);
if (! $result->has_rows())
{
echo "No other users with $user->wantedCardId were found.";
continue;
}
$cardHolder = $result->row();
echo: "User $cardHolder->id gives $user->id his card";
}
//Populate an array containing a list of all the users and their cards.
$users = array();
$user[1] = new StdClass();;
$user[1]->cardId = 2;
$user[1]->wantedId = 3;
$user[2] = new StdClass();
$user[2]->cardId = 3;
$user[2]->wantedId = 2;
// .....
foreach ($users as $userId=>$user)
{
//Run a secondary loop through the users to find those that have the card that
//this user wants.
foreach ($users as $holderId=>$cardHolder)
{
if ($cardHolder->cardId != $user->wantedId)
continue;
echo "User $holderId gives $userId his card";
}
}
如果我使用普通PHP进行此操作,我将执行以下操作:
$sql = "SELECT * FROM users";
$result = $this->db->query();
$users = $result->getAll(); //A list of all the users.
foreach ($users as $user)
{
$sql = "SELECT * FROM users WHERE cardId = '$user->wantedCardId'";
$result = $this->db->query($sql);
if (! $result->has_rows())
{
echo "No other users with $user->wantedCardId were found.";
continue;
}
$cardHolder = $result->row();
echo: "User $cardHolder->id gives $user->id his card";
}
//Populate an array containing a list of all the users and their cards.
$users = array();
$user[1] = new StdClass();;
$user[1]->cardId = 2;
$user[1]->wantedId = 3;
$user[2] = new StdClass();
$user[2]->cardId = 3;
$user[2]->wantedId = 2;
// .....
foreach ($users as $userId=>$user)
{
//Run a secondary loop through the users to find those that have the card that
//this user wants.
foreach ($users as $holderId=>$cardHolder)
{
if ($cardHolder->cardId != $user->wantedId)
continue;
echo "User $holderId gives $userId his card";
}
}
您可以用有向图来表示问题。用户是图形的顶点,边表示用户X拥有用户Y想要的卡。您不需要代表碰巧拥有所需卡片的用户 该问题的解决方案是一组边,确保每个顶点只有一条输出边,而只有一条输入边 编辑 我忽略了一个事实,即一个用户可能有多张卡。我想他可能还需要几张牌。在这种情况下,我将每个用户表示为一个顶点,每个X都需要一张Y作为边的卡,即使X等于Y。然后问题的解决方案是一组边,使每个人都有他们想要的卡,并且不允许任何用户多次给同一张卡 我会给每张卡分配一个数字,并记录每个用户在乞讨时每个数字有多少张卡,以及用户有多少个相同数字的输出边来检查。如果一个用户从不“想要”他“拥有”的类型来计算它可以完成的方式,组合数学就足够了,不需要算法。如果要“显示”交换发生的方式,则: 要可视化问题,请按以下方式排列类型:
TYPE A ........................... TYPE N
| | | |
| | | |
| USER 2 | | |
| USER 1 | | |
| USER 1 | +..........+
+----------+
HAS
WANTS
+----------+
| USER 3 |
| USER 4 |
| USER 5 |
| |
在我们的示例中,用户1有两张A型卡,用户2有一张,用户3、4和5各想要一张A型卡
让我们在这一刻思考一下A型卡片
您需要成对交换卡片,如顺序卡片:
{{usr 1,usr3},{usr1, usr 4}, {usr2,usr5}}
如果每个用户都满意,那么会有和询问者相同的所有者
现在,要形成成对,您知道必须在不重新定位的情况下从每个集合中拾取一个元素。因为可能会有重复(用户想要或拥有一种类型的多张卡),所以您也必须考虑到这一点。这是为了计算每种类型应“处理”的方式。组合数学就足够了
要形成成对,您可以:
1) 构造每个集合的所有不同排列:
{2, 1, 1} {1, 2, 1} {1, 1, 2} # == 3!/2!
{3, 4, 5} {5, 3, 4} {4, 5, 3} {4, 3, 5} {5, 4, 3} {3, 5, 4} # == 3!
2) 在我们的示例中,对于每一对排列,都有一个不同的结果集3 x 6=18。
对所有卡类型执行相同操作
最后,对于每种卡片类型,您有N个可能的结果集。为了获得交换所有卡片的所有可能方式,您必须为每种类型组合所有可能方式 这与PHP无关,删除PHP标记以便更多用户查看它。是否会限制您拥有的卡和用户数量?这可能是一个很难解决的问题。您可以将任何置换分解为一系列循环,这是一个开始:您将不得不进行某种约束,否则您将有无限多的解决方案(例如1,2保持交换卡)。