不确定以下情况是否属于背包问题或硬币变更方法。想在PHP语言中寻求解决这个问题的方法。需要简单的解决方案,因为不了解互联网提供的一些算法(文本理论)。
鉴于表(A)如下:
TABLE (A)
---------
Item | Name | Price ($)
-------- ------------ --------------
1 | Adidas | 35
2 | Nike Run | 70
3 | Puma | 100
4 | Nike | 85
5 | NB | 65
结果:
Item | Name | Price ($)
-------- ------------ --------------
1 | Adidas | 35
5 | NB | 65
3 | Puma | 100
给出另一个样本表(B)如下:
TABLE (B)
---------
Item | Name | Price ($)
-------- ------------ --------------
1 | Adidas | 5
2 | Nike Run | 35
3 | Puma | 110
4 | Nike | 65
5 | NB | 15
结果:
Item | Name | Price ($)
-------- ------------ --------------
2 | Nike Run | 35
4 | Nike | 65
3 | Puma | 110
答案 0 :(得分:0)
假设表A是一个关联数组,我们称之为$ a。 要找到将> = 200的第一个组合,请执行以下操作:
$rowsWithValueOver200 = array();
foreach($a as $value) {
foreach($a as $value2) {
// Make sure to ignore the value selected in the first loop.
if ($value2 == $value)
continue;
foreach($a as $value3) {
// Make sure to ignore the value selected in the first and second loop.
if ($value3 == $value)
continue;
if ($value3 == $value2)
continue;
$total = $value3['Price'] + $value2['Price'] + $value['Price'];
if ($total >= 200) {
// Store all of the rows in the new array.
$rowsWithValueOver200[] = $value;
$rowsWithValueOver200[] = $value2;
$rowsWithValueOver200[] = $value3;
break;
}
}
}
}
所以我们遍历数组3次。一旦我们查看3个唯一值,请检查总和。始终确保我们不包含先前选择的数组元素($ value或$ value2)。这当然可以稍微清理一下并且更加通用,但它可以用于3个元素。将其重构为更通用的函数将对其自身进行递归调用,允许起始位置(然后使用for循环而不是foreach)。
要找到最小值非常简单。
$minVal = PHP_INT_MAX; // Initially something high, here it is the maximum integer value.
$minRow;
foreach($rowsWithValueOver200 as $value) {
if ($value['Price'] < $minVal){
$minVal = $value['Price'];
$minRow = $value;
}
}
设置最小值(minVal)以检查真正高的值。迭代数组值,如果$ value [&#39; Price&#39;]小于当前的minVal,那么它现在是minVal并将数组元素存储在$ minRow中供以后参考。
3和4我不确定你在问什么。目前尚不清楚。 如果你想在$ rowsWithValueOver200中找到三行的总和,那么你可以使用我在第一个答案中的内容。如果你想只用3个最终元素来做,那就这样做:
$total = 0;
foreach($rowsWithValueOver200 as $value) {
$total += $value['Price'];
}
如果您正在寻找总计200或更多的其他可能性,那么只需使用第一个示例,但在第一个循环中使用带有索引的for循环而不是foreach。从每个索引开始。
祝你好运!答案 1 :(得分:0)
MySQL已经适当地装备完成这一切。您可以拉出整个表格以供PHP使用,但这可能会使资源变得昂贵,而且肯定会产生较慢的结果,尤其是对于较大的数据库。 PHP通常需要多次遍历数据才能进行足够的数组操作,MySQL可以很容易地完成这些操作。
假设您的数据库如下所示:
CREATE TABLE IF NOT EXISTS `A` (
`Item` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(10) NOT NULL,
`Price` decimal(10,2) NOT NULL,
PRIMARY KEY (`Item`),
UNIQUE KEY `Name` (`Name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
INSERT INTO `A` (`Item`, `Name`, `Price`) VALUES
(1, 'Adidas', '35.00'),
(2, 'Nike Run', '70.00'),
(3, 'Puma', '100.00'),
(4, 'Nike', '85.00'),
(5, 'NB', '65.00');
您可以这样查询:
SELECT @leastprice := min(`Price`) FROM `A`;
SELECT t1.Name AS Name1, t2.Name AS Name2, t3.Name AS Name3,
t1.Price AS Price1, t2.Price AS Price2, t3.Price AS Price3,
(t1.Price+t2.Price+t3.Price) AS `Total`
FROM `A` t1
LEFT JOIN `A` t2 ON t1.Item != t2.Item
LEFT JOIN `A` t3 ON t1.Item != t2.Item AND t2.Item != t3.Item
WHERE t1.price = @leastprice
AND t2.price<=t3.price
AND t1.price+t2.price+t3.price >= 200;
结果:
<小时/> 修改强>
CREATE TABLE IF NOT EXISTS `B` (
`Item` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(10) NOT NULL,
`Price` decimal(10,2) NOT NULL,
PRIMARY KEY (`Item`),
UNIQUE KEY `Name` (`Name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;
INSERT INTO `B` (`Item`, `Name`, `Price`) VALUES
(1, 'Adidas', '5.00'),
(2, 'Nike Run', '35.00'),
(3, 'Puma', '110.00'),
(4, 'Nike', '65.00'),
(5, 'NB', '15.00');
您可以这样查询:
SELECT @leastTalliablePrice := min(t1.Price) FROM `B` t1
LEFT JOIN `B` t2 ON t1.Item != t2.Item
LEFT JOIN `B` t3 ON t1.Item != t2.Item AND t2.Item != t3.Item
WHERE t2.price<=t3.price
AND t1.price+t2.price+t3.price >= 200;
SELECT t1.Name AS Name1, t2.Name AS Name2, t3.Name AS Name3,
t1.Price AS Price1, t2.Price AS Price2, t3.Price AS Price3,
(t1.Price+t2.Price+t3.Price) AS `Total`
FROM `B` t1
LEFT JOIN `B` t2 ON t1.Item != t2.Item
LEFT JOIN `B` t3 ON t1.Item != t2.Item AND t2.Item != t3.Item
WHERE t1.price = @leastTalliablePrice
AND t2.price <= t3.price
AND t1.price+t2.price+t3.price >= 200;
结果:
如果由于某种原因,您的数据库没有3个或更多不同的项目,或者它们的价格不足以达到您想要的总数,那么查询将以与SELECT相同的方式返回0行结果为0行,如果它找不到要选择的行。但如果在上述情况下有多个匹配,则会产生多行,就像我的第一个屏幕截图中的情况一样。