문제 :
1, 5, 10, 20 사가지 컨버터블 알려진 유형을 변경, 몇 가지가 거기에 있습니다,이 100 달러이며, 동전의 총 수는 15 개 미만의 교체? 그들은 무엇입니까?
아이디어 :
그것은 공지된다 1,5,10,20 이러한 임의의 데이터는 현재 수 (n)으로부터 제거 S를 설정, 각 숫자의 수가 a2xn2 + ... + = 100 aixni a1xn1 등이다.
최대 교는 100/20 = 5 총 20이고,이 시트의 최소한의 수이며, 하한은 5 개주기 정의 된 피사체의 상한 (15)이다.
즉,이 데이터 세트로부터 S이다 5-15의 번호를 가지고, 그들의 횟수 반복 될 수있다 (100) 등.
먼저 간단한 경우를 고려한다. 100은 한계로 간주되지 않습니다. 데이터 세트 S (5)의 숫자에서만 찍은 숫자는이 상황을 반복 얼마나 많은 수있다?
우리의 문제에서, 주문 번호는 다음과 같은 요구 사항, 꺼내되지 않은 : 그래서, [1,5,5,10,20] 사이에 차이가 [1,20,10,5,5]입니다 꺼내 이 문제의 조합입니다.
그러나 일반적으로 상기 N 개의 상이한 수 m에서 문제의 조합으로부터 선택되고, 화학식이 C (m, N)이다.
그러나 우리는 여기 반복의 수를 허용하는 것입니다, 어떻게합니까? 우리가 걸릴 경우 어떻게, 변환 될 수있다 [1,1,1,1,1]이 횟수 5 (즉, N = 5), 우리는 일정한 우선, 나머지 수를 유지할 수있다 (4) (즉, N-1 ) 더하기 하나 이상의 임의의 수 (100)의 모든 S의 다른 요소가 상이되도록, 그것은 1-N 고유 번호 m + 수식은 C이다 (m + N- N 개의 찍은 숫자에 해당 1, N). 확인합니다.
: S 두을 [1,5] 인 경우, 우리는 다음의 조성을 구하는
[1,1], [1,5], [5,5] 세 종류의 총.
, C (2-1,2 + 2) 식을 이용하여 계산 = C (3,2) = 3; 올바르게.
그런 다음 세에서 촬영하는 경우의 조합에 의해 얻어 질 수있다
[1,1,1], [5,1,1], [5,5,1], [5,5,5] 네 종류의 총.
식, C (3-1,3 + 2) = 계산 4; 올바르게.
반복 회수 될 수 N의 상이한 수 m에서 추출되어 C의 조합의 수 (m + N-1, N) 인
이제 이러한 조합이 목록에 넣어, 당신은 다음과 같은 방법을 사용할 수 있습니다 :
우리는 각 요소의 S 인덱스를 저장하는 데 사용되는 임시 배열을 설정합니다.
[0,0,0,0,0]로 초기화되며, 5 S [0]이된다 찍은 모든 요소 나타내는
표시 후 처음으로 추가 1 [1,0,0,0,0]를해진다을 의 양 [5,1,1,1,1]
첫 번째 장소는 결국 [3,0,0,0]이 될 것이다, 모든 프로그램 일정 S의 완료 될 때까지 계속 누적;
이 즉 공정의 제 1 원형이다
[0,0,0,0,0]
[1,0,0,0,0]
[2,0,0,0,0]
, [3,0,0 0,0]
다음, 세 개 이상의 요소의 첫번째 인덱스 최초 두 개의 프로세스, 즉, 처리시에 :
[1,1,0,0,0]는
그 제 1 적산 계속
[2,1,0,0을 0]
[3,1,0,0,0]
제 3을 초과 할 경우, 첫 번째 두 축적된다
[1,2,0,0,0]를
다음 선입 계속 축적
[2,2,0,0,0]
[3,2,0,0,0]를
모든 요소가 될 때까지이 프로세스는 반복된다
[3,3,3,3,3]를
여섯 번째 요소 값을 가질 때, 그 고려 될 수 있도록 여분의 하나에 배열 인덱스가 끝난 것으로 있도록 그러나이 조건이 좋지 않아 세 심사 위원, 우리는 하나를 추가 할 수 있습니다.
요소가 [1,1,1,1,1,1] 프로그램이 종료 될 때, 즉 표준이다.
모든 배열 인덱스 함께 집계 데이터 요소들의 대응하는 세트로 매핑, 즉, 최종 결과이다.
답변 :
PHP
/**
* 取元素可重复的组合
* @param $arr array 可选择元素数组
* @param $n int 要取的数量
* @return array
*/
function repeatedCombination($arr, $n)
{
$len = count($arr);// 数组长度
$tmp = array_fill(0, $n + 1, 0);// 存放组合元素的下标,初始为0
$len--; // 数组长度减1
$result = array();
while (1) {
for ($i = 0; $i < $n; ++$i) { // n个元素
if ($tmp[$i] > $len) {
$tmp[$i + 1] += 1;
for ($j = $i; $j >= 0; --$j) {
$tmp[$j] = $tmp[$j + 1];
}
}
}
// 当最后一位非0时,所有的组合都已经处理完毕,退出
if ($tmp[$n] > 0) {
break;
}
$item = array();
for ($i = 0; $i < $n; $i++) {
$item[] = $arr[$tmp[$i]];
}
$result[] = $item;
$tmp[0] += 1;
}
return $result;
}
$arr = array("1", "5", "10", "20");
$m = array();
for ($i = 5; $i < 15; $i++) {
$rs = repeatedCombination($arr, $i);
foreach ($rs as $r) {
if (array_sum($r) == 100) {
$m[] = $r;
}
}
}
print_r($m);
출력 :
Array
(
[0] => 20-20-20-20-20
[1] => 20-20-20-20-10-10
[2] => 20-20-20-20-10-5-5
[3] => 20-20-20-10-10-10-10
[4] => 20-20-20-20-5-5-5-5
[5] => 20-20-20-10-10-10-5-5
[6] => 20-20-10-10-10-10-10-10
[7] => 20-20-20-10-10-5-5-5-5
[8] => 20-20-10-10-10-10-10-5-5
[9] => 20-10-10-10-10-10-10-10-10
[10] => 20-20-20-10-5-5-5-5-5-5
[11] => 20-20-10-10-10-10-5-5-5-5
[12] => 20-10-10-10-10-10-10-10-5-5
[13] => 10-10-10-10-10-10-10-10-10-10
[14] => 20-20-20-20-10-5-1-1-1-1-1
[15] => 20-20-20-5-5-5-5-5-5-5-5
[16] => 20-20-10-10-10-5-5-5-5-5-5
[17] => 20-10-10-10-10-10-10-5-5-5-5
[18] => 10-10-10-10-10-10-10-10-10-5-5
[19] => 20-20-20-20-5-5-5-1-1-1-1-1
[20] => 20-20-20-10-10-10-5-1-1-1-1-1
[21] => 20-20-10-10-5-5-5-5-5-5-5-5
[22] => 20-10-10-10-10-10-5-5-5-5-5-5
[23] => 10-10-10-10-10-10-10-10-5-5-5-5
[24] => 20-20-20-10-10-5-5-5-1-1-1-1-1
[25] => 20-20-10-10-10-10-10-5-1-1-1-1-1
[26] => 20-20-10-5-5-5-5-5-5-5-5-5-5
[27] => 20-10-10-10-10-5-5-5-5-5-5-5-5
[28] => 10-10-10-10-10-10-10-5-5-5-5-5-5
[29] => 20-20-20-10-5-5-5-5-5-1-1-1-1-1
[30] => 20-20-10-10-10-10-5-5-5-1-1-1-1-1
[31] => 20-10-10-10-10-10-10-10-5-1-1-1-1-1
[32] => 20-20-5-5-5-5-5-5-5-5-5-5-5-5
[33] => 20-10-10-10-5-5-5-5-5-5-5-5-5-5
[34] => 10-10-10-10-10-10-5-5-5-5-5-5-5-5
)
golang :
package main
import (
"fmt"
"strconv"
)
func main() {
data := []string{"1", "5", "10", "20"}
m := make([][]string, 0)
for i := 5; i < 15; i++ {
rs := repeatedCombination(data, i)
for _, r := range rs {
sum := 0
for _, v := range r {
val, _ := strconv.Atoi(v)
sum += val
}
if sum == 100 {
m = append(m, r)
}
}
}
fmt.Println(m)
}
func repeatedCombination(data []string, n int) [][]string {
length := len(data)
limit := length - 1
tmp := make([]int, n+1)
result := make([][]string, 0)
for {
for i := 0; i < n; i++ {
if tmp[i] > limit {
tmp[i+1] += 1
for j := i; j >= 0; j-- {
tmp[j] = tmp[j+1]
}
}
}
if tmp[n] > 0 {
break
}
var item []string
for i := 0; i < n; i++ {
item = append(item, data[tmp[i]])
}
result = append(result, item)
tmp[0] += 1
}
return result
}
출력 :
[[20 20 20 20 20]
[20 20 20 20 10 10]
[20 20 20 20 10 5 5]
[20 20 20 10 10 10 10]
[20 20 20 20 5 5 5 5]
[20 20 20 10 10 10 5 5]
[20 20 10 10 10 10 10 10]
[20 20 20 10 10 5 5 5 5]
[20 20 10 10 10 10 10 5 5]
[20 10 10 10 10 10 10 10 10]
[20 20 20 10 5 5 5 5 5 5]
[20 20 10 10 10 10 5 5 5 5]
[20 10 10 10 10 10 10 10 5 5]
[10 10 10 10 10 10 10 10 10 10]
[20 20 20 20 10 5 1 1 1 1 1]
[20 20 20 5 5 5 5 5 5 5 5]
[20 20 10 10 10 5 5 5 5 5 5]
[20 10 10 10 10 10 10 5 5 5 5]
[10 10 10 10 10 10 10 10 10 5 5]
[20 20 20 20 5 5 5 1 1 1 1 1]
[20 20 20 10 10 10 5 1 1 1 1 1]
[20 20 10 10 5 5 5 5 5 5 5 5]
[20 10 10 10 10 10 5 5 5 5 5 5]
[10 10 10 10 10 10 10 10 5 5 5 5]
[20 20 20 10 10 5 5 5 1 1 1 1 1]
[20 20 10 10 10 10 10 5 1 1 1 1 1]
[20 20 10 5 5 5 5 5 5 5 5 5 5]
[20 10 10 10 10 5 5 5 5 5 5 5 5]
[10 10 10 10 10 10 10 5 5 5 5 5 5]
[20 20 20 10 5 5 5 5 5 1 1 1 1 1]
[20 20 10 10 10 10 5 5 5 1 1 1 1 1]
[20 10 10 10 10 10 10 10 5 1 1 1 1 1]
[20 20 5 5 5 5 5 5 5 5 5 5 5 5]
[20 10 10 10 5 5 5 5 5 5 5 5 5 5]
[10 10 10 10 10 10 5 5 5 5 5 5 5 5]]