그 일이 일어난 이유
저희 회사에서 알고리즘 프로그래밍 대회를 했는데, 아래 사진의 알고리즘 문제를 무작위로 뽑았기 때문에 잠시 고민하다가 책에 알고리즘이 있다는 걸 기억해냈어요(알고리즘 일러스트레이션) ) 그것이 더 적합했습니다. 즉, "배낭 문제"의 알고리즘이었습니다.
Knapsack 문제는 조합 최적화의 NP-완전 문제입니다. 문제는 다음과 같이 설명할 수 있습니다. 품목 세트가 주어지면 각 품목에는 고유한 무게와 가격이 있습니다. 제한된 총 무게 내에서 품목의 총 가격이 가장 높도록 어떻게 선택합니까?
주어진 배낭에 넣을 가장 적절한 품목을 선택하는 방법은 우리의 질문과 일치하므로 이번에는 "0-1 배낭 문제"를 사용하고 이번에는 질문을 "총 인원수"로 대체하여 사용합니다. "배낭"에서 "아이템"은 "작업지시 유형"에 해당하며, 아이템의 무게는 필요한 인원수입니다.
보충:
배낭 문제 풀이에는 세 가지 확장 문제가 있습니다: 무한 배낭 문제, 0-1 배낭 문제, 2차 배낭 문제(자세한 확장이 없고 우리가 사용하는 것)
알고리즘 질문은 다음과 같습니다. 다음과 같이
동적 프로그래밍에서 다루는 문제는 다단계 의사결정 문제로, 일반적으로 초기 상태에서 시작하여 중간 단계 의사결정의 선택을 거쳐 최종 상태에 도달합니다. 이러한 결정은 결정 순서를 형성하고 전체 프로세스를 완료하기 위한 활동 경로(일반적으로 최적의 활동 경로)를 결정합니다. 동적 프로그래밍의 설계에는 일반적으로 다음 단계를 포함하는 특정 패턴이 있습니다.
초기 상태→│결정 1│→│결정 2│→…→│결정n│→종료 상태
동적 프로그래밍 문제 해결 공식:
f(n,m)=max{f(n-1,m),f(n-1,m-w[n])+P(n,m)}
● 가로 m(총 인원), 세로 n (4대의 차량이 수행한 작업지시 유형)
● f(n-1,m) ==> (결정 1) 이전 작업지시 유형에 해당하는 기술자 수 및 수행한 작업지시 수익
● P(n, m) ==> (결정 2) 현재 작업지시 유형에 해당하는 기술자 수 및 작업지시 수익
● f(n-1,m-w[n]) = => 인원수에서 현재 작업 지시에 필요한 금액, 이전 결정의 인원수에 해당하는 이익을 뺍니다.
그래서 최적의 솔루션에 대한 답은 다음과 같습니다. 기술자 결정 n, 1799위안
PostMan 제출 매개변수:
people:5 carDetail[0][technician]:2 carDetail[0][amount]:49 carDetail[0][type]:全车安检 carDetail[1][technician]:2 carDetail[1][amount]:499 carDetail[1][type]:深度诊断 carDetail[2][technician]:3 carDetail[2][amount]:1300 carDetail[2][type]:二手车检测 carDetail[3][technician]:1 carDetail[3][amount]:10 carDetail[3][type]:空调专项检测
답변 방법 1: 동적 프로그래밍
<?php // 动态规划 error_reporting(E_ALL ^ E_NOTICE); $t1 = microtime(true); class bestMatch { public function getMethod($postData) { $peopleArr = $gainArr = $nameArr = [0]; foreach ($postData['carDetail'] as $val) { // 初始化各个套餐:所需人数、利润和套餐名称数组 $peopleArr[] = $val['technician']; $gainArr[] = $val['amount']; $nameArr[] = $val['type']; } // 获取人数总数(背包) $totalPeople = $postData['people']; // 做检测单数 $items = count($peopleArr); // 利润列表 - 初始状态 $cacheMap[] = array_fill(1, $items, 0); // 套餐列表 - 初始状态 $cacheMapName[] = array_fill(1, $items, ''); //中间的各种决策(依次放入物品a,b,c,d,e) // 第一个循环是总人数 for($i = 1; $i <= $totalPeople; $i++) { // 第二个循环是套餐 for($j = 1; $j < $items; $j++) { $requiredPeople = $peopleArr[$j]; $gain = $gainArr[$j]; $name = $nameArr[$j]; // 上一行坐标数 $preLine = $j-1; $prevGain = $cacheMap[$preLine][$i]; $prevName = $cacheMapName[$preLine][$i]; if($requiredPeople > $i) { $cacheMap[$j][$i] = $prevGain; $cacheMapName[$j][$i] = $prevName; } else { // 剩余价值 if ($i-$requiredPeople >= 0) { $surplusPeople = $i-$requiredPeople; $surplusGain = $cacheMap[$preLine][$surplusPeople]; $surplusName = $cacheMapName[$preLine][$surplusPeople]; }else { $surplusGain = 0; $surplusName = ''; } $nowTotalGain = $gain + $surplusGain; $cacheMap[$j][$i] = max($prevGain, $nowTotalGain); if ($prevGain > $nowTotalGain) { $cacheMapName[$j][$i] = $prevName; }else{ $cacheMapName[$j][$i] = $name.'+'.$surplusName; } } } } $actual = count($postData['carDetail']); return [ 'maxMatch' => $cacheMap[$actual][$totalPeople], 'maxMatchName' => trim($cacheMapName[$actual][$totalPeople],'+') ]; } } $bestMatch = new bestMatch; if (empty($_POST) || isset($_POST['people']) && $_POST['people'] > 0) { die('提交参数有误'); } $res = $bestMatch->getMethod($_POST); $t2 = microtime(true); echo '动态规划: '.'<br/>'; echo '最佳金额: '.$res['maxMatch'].'<br/>'; echo '最佳套餐搭配: '.$res['maxMatchName'].'<br/>'; echo '耗时'.round($t2-$t1,7).'秒'.'<br/>' ; echo '消耗内存: ' . memory_get_usage().'字节'.'<br/>' ;
해결 방법 2: 재귀
<?php // 递归查询 error_reporting(E_ALL ^ E_NOTICE); $t1 = microtime(true); class optimal { public function getSortList($array,$index = 0,$up =0,&$result =[]) { for ($i=$index; $i < count($array); $i++) { if($index > 0 ){ $value['name'] = $up['name'].'+'.$array[$i]['type']; $value['amount'] = bcadd($up['amount'],$array[$i]['amount']); $value['technician'] = bcadd($up['technician'],$array[$i]['technician']); }else{ $value['name'] = $array[$i]['type']; $value['amount'] = bcadd($array[$i]['amount'],0); $value['technician'] = bcadd($array[$i]['technician'],0); } $result[] = $value; $this->getSortList($array,$i+1,$value,$result); } return $result ; } public function getMethod($postData) { $people = $postData['people']; $carDetail = $postData['carDetail']; $allResult = $this->getSortList($carDetail); $bestMatch = []; foreach ($allResult as $val) { if ($val['technician'] <= $people) { if ($bestMatch) { if ($val['amount'] > $bestMatch['amount']) { $bestMatch = $val; } }else{ $bestMatch = $val; } } } return $bestMatch; } } $optimal = new optimal(); if (empty($_POST) || isset($_POST['people']) && $_POST['people'] > 0) { die('提交参数有误'); } $bestMatch = $optimal->getMethod($_POST); $t2 = microtime(true); echo '递归查询: '.'<br/>'; echo '最佳金额: '.$bestMatch['amount'].'<br/>'; echo '最佳套餐搭配: '.$bestMatch['name'].'<br/>'; echo '耗时'.round($t2-$t1,7).'秒'.'<br/>' ; echo '消耗内存: ' . memory_get_usage().'字节'.'<br/>' ;
위 내용은 PHP는 동적 프로그래밍 배낭 문제를 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!