動態規劃 001 複雜的整數劃分問題

2021-10-04 04:22:32 字數 3642 閱讀 8482

總時間限制: 200ms 記憶體限制: 65536kb

描述

將正整數n 表示成一系列正整數之和,n=n1+n2+…+nk, 其中n1>=n2>=…>=nk>=1 ,k>=1 。

正整數n 的這種表示稱為正整數n 的劃分。

輸入

標準的輸入包含若干組測試資料。每組測試資料是一行輸入資料,包括兩個整數n 和 k。

(0 < n <= 50, 0 < k <= n)

輸出

對於每組測試資料,輸出以下三行資料:

第一行: n劃分成k個正整數之和的劃分數目

第二行: n劃分成若干個不同正整數之和的劃分數目

第三行: n劃分成若干個奇正整數之和的劃分數目

樣例輸入

5 2
樣例輸出

2

33

提示

第一行: 4+1, 3+2,

第二行: 5,4+1,3+2

第三行: 5,1+1+3, 1+1+1+1+1+1

#include

#include

using

namespace std;

//a[i][j] 和為i, j個正整數

////第一行: n劃分成k個正整數之和的劃分數目 a[i][j] j=k

//第二行: n劃分成若干個不同正整數之和的劃分數目 b[i][j] i=n不同正整數

//第三行: n劃分成若干個奇正整數之和的劃分數目 c[i][j] i=n 奇正整數

//a//初始狀態: a[i][1]=1

//分類——包含1和不包含1

//a[i][j]=a[i-1][j-1]

// +1就為當前值——故必包含1

// if i-j>j ---- a[i][j]+=a[i-j][j] 每個整數-1,則原來為1的就為0了

int a[60]

[60]=

;voidq1(

int n,

int k)

for(

int i=

1;i<=n;i++)}

}}//n劃分成若干個不同正整數之和的劃分數目

//最大值為t=n的不同正整數之和

//b[i][j]= 不包括n和包括n 從前t(1——t)種數字鐘選擇一些——湊成和i的做法數目

// 如果i=0; return1;

// 如果t=0; return0;

// return [i][t-1]+[i-t][t-1]

int b[60]

[60]=

;voidq2(

int n,

int t)}}

// n劃分成若干個奇正整數之和

//與整數拆法類似——考慮有沒有1

//沒有1—— -2*j

//因為沒有1的話最小的就為3以上

//c[i][j]=c[i-2*j][j]+c[i-1][j-1]

// 沒有1的 所有有1的

// 每個都減去2 ——減一的話就都剩偶數了——-2就為計數

int c[60]

[60]=

;voidq3(

int n,

int t)

for(

int i=

2;i<=n;i++)}

}}int n;

int k;

intmain()

}

解題思路

使用動態規劃需要滿足的條件:

子問題的最優解可以用於遞推母問題的最優解;

問題一

將n劃分成k個正整數之和,求可劃分的數目。

a[i][j]表示j個正整數求和為i;

目標為a[n][k]

初始狀態:a[i][1]=1

難點:

分類方法: 表示式中包含1和不包含1

包含1的表示式——a[i][j]=a[i-1][j-1],即前乙個數所有的表示式+1即可;

不包含1的表示式——a[i-j][j],當作最小為2,則每個數-1後最小為1。

int a[60]

[60]=

;voidq1(

int n,

int k)

for(

int i=

1;i<=n;i++)}

}}

問題2

n劃分成若干個不同正整數之和的劃分方法總數;

b[i][j], i劃分成小於等於j的不同正整數之和的劃分方法數;

目標為b[n][n]

初始狀態:b[0][0]=1; ——0的和為0

難點:

遞推方法 ——當前b[i][j]的方法數等於包含j和不包含j的方法數相加

遞推公式

不包含j的方法數——b[i][j-1]

包含j的方法數——b[i-j][j-1] (i>=j時),i遞推方向——(先從左往右推)——(再從上往下推)–初始狀態確定0,0即可

int b[60]

[60]=

;voidq2(

int n,

int t)

}}

問題3

n劃分成若干個奇正整數之和,求劃分方法數

c[i][j]——用j個數求和i

總劃分數為i行所有j的和。

初始狀態——c[i,i為奇數][1]=1,因為乙個數只有一種表示式

分類方法

包含1——c[i-1][j-1]

不包含1——c[i-2j][j], (i>3j),因為如果i<3*j,表示式中必含1

目標為c[n][1]加到c[n][n]的和;

int c[60]

[60]=

;voidq3(

int n,

int t)

for(

int i=

2;i<=n;i++)}

}}

與問題一:n劃分成k個整數之和的劃分方法數做法相同。

k從1取到n的和就為總的方法數;

求j個數中不包含1的和為i的表示式

此表示式全部大於等於3,則每個數-2,最小值為1,也有不包含1的。

[i-2j][j]的總數為[i][j]中不包含1的數量。

動態規劃解整數劃分

演算法思路 n n1 n2 n3 n4 nk n1 n2 n3 nk 從大到小排列後,可以避免陷入數值大小排序順序的困境中。這樣,在下面的過程,我們可以並不關心數值大小的排列,只關心組合方案數。狀態表示 將最大加數n1不大於m的劃分個數記作q n,m 狀態轉移 1 q n,1 1,n 1 當最大加數...

整數劃分問題 動態規劃

原文出處 整數劃分 有以下情況 1 將n劃分成若干正整數之和的劃分數。2 將n劃分成k個正整數之和的劃分數。3 將n劃分成最大數不超過k的劃分數。4 將n劃分成若干奇正整數之和的劃分數。5 將n劃分成若干不同整數之和的劃分數。include includeconst int ns 55 int n,...

DP 動態規劃 整數劃分

時間限制 3000 ms 記憶體限制 65535 kb 難度 3 輸入第一行是測試資料的數目m 1 m 10 以下每行均包含乙個整數n 1 n 10 輸出輸出每組測試資料有多少種分法。描述將正整數n表示成一系列正整數之和 n n1 n2 nk,其中n1 n2 nk 1,k 1。正整數n的這種表示稱為...