整数除算の問題動的計画

ACM、OIおよび他のゲーム、一般的なエントリのタイトルに分け整数、徐Jiumeiがゲームをプレイするには、最近、把握今のノートを作るために長い時間のためにつまずき、突然の出会いペンの質問をしました。

-------------------------------------------------- -----------------------------------

トピック見えるhduoj1028  、単純に言います:

数Nは、組み合わせの数は、整数個に分割されています。これは、整数除算を表し、そのようなものとして、正の整数Nに設定すると、N = 4:

  4 = 4。
  4 = 3 + 1。
  4 = 2 + 2。
  4 = 2 + 1 + 1。
  4 = 1 + 1 + 1 + 1。

5この場合、組み合わせの数N = 4分割から5の整数を持っています。

-------------------------------------------------- -----------------------------------

問題解決の状態のための最初のDP、DPの設計を開始します。

ステップ思考:組み合わせを考慮すること「の使用は、このような3 = 4 + 1 + 1 = 3と4のように見えることができない繰り返し状況、ある最大値の分割数が」状態を繰り返すように定義されています。

ステップ考察:状態設計:DP [n]は「[n]を意味分割の最大数はMであり、そしてnは、組み合わせの数」。

考慮第三段階:状態遷移:分割数はMが含まれている二つの状態、二つの状態の組み合わせの数及び組み合わせの数に等しい電流に分割されます。

  1. N = 1、Mは関係なく、パーティショニングの一種のみ{1}、DPを有していてどのように多くの同じである[1] [M] = 1
  2. M = 1、N [1] = 1分割、DP [n]は,,,,,,かかわらず唯一{1,1,1}のあるどのように多くの等しいです
  3. N == M、2例、DP [n]は[M] = 1 + DP [n]は[M-1]:
    1. 分割数mを含有し、一方のみ{M}
    2. 分割数は、MにのみDP [n]は[M-1]として、M-1であることができる最大値が含まれていない場合
  4. N> Mの場合、Mは最大n個のみ取ることができ、DP [n]は[m]はDPを= [N] [N]
  5. N <M、2例、DP [n]は[m]はDPを= [nm]と[M] + DP [n]は[M-1]:
    1. 分割数Mに含まれる場合、最終的な数は、合計(Mを有することができる前に)m個に分割しなければならない{........ M} = N、DP [nm]と[M]
    2. 分割数をmに含まれていない場合、M-1に分割することができる最大数、DP [n]は[M-1]

 

再帰的なコードのメモリを入れて、より便利再帰:

#include <iostreamの>
 使用して 名前空間STD;
 CONST  INT MAXN = 128 ;
 int型 DP [MAXN] [MAXN] = { 0 };
 int型 DP(INT N-、INT M)
{ 
    // 不正
    IF N( - <= 0 | | M <= 0戻り 0 ; 

    // のメモリ
    IFは(DPは[N-] [M]> 0を返すDP [N-] [M]; 

    // 1つのみのn-1 = {1}; 
     // 2. M = 1つのみ,,,,,, 1,1,1} { 
    IF == - (nは1。M == || 1。 を返す DP [N-] [M] = 1 ; 

    // 1. mが一つだけ} M {含ま
     // 2. Mを含有しない、DP [N-] [-m 1]
     // のN- == M、両方のすべてのケースのための
    IF(== N-M)戻り DP [N-] [M] = 1 + DP(N、M - 1。); 

    // 最大でMは、N- 
    IF(N- <M)   を返す DPが[N-] [m]は= ;)(N、N- DP 

    // 最後M、DP [nm]と[M]の数として、Mを含む1.
     // 2. Mを含有しない、最大数1-M、行う[N-] [-m 1]
     // N-> M、すべてのケースの両方に対して
    IF(N> M)   リターン DP [N-] [m]はDP(N-- mは、= M)DP +(N、M - 1); 

    // 不正
    戻り DP [N-] [M] = 0 ; 
} 
int型のmain()
{ 
    int型N-、
     一方(CIN >> N-){ 
        COUT << DP(N、N-)<< ENDL; 
    } 
    リターン 0 ; 
}

 

DP再帰バージョン

#include <iostreamの>
 使用して 名前空間STD;
 CONST  INT MAXN = 128 ;
 int型 DP [MAXN] [MAXN] = { 0 ;}
 無効(INITをINT MAXN)
{ 
    ためINT N- = 1 ; N - <= MAXNを; N - ++ ){
         int型、M = 1、M <= MAXNあり; m ++ ){ 
            
            // N-1 =、mは関係なく等しい何有するパーティションの一種のみ{1}、DP [1] [M] = 1
             // M =図1に示すように、Nは関係なく等しい何のみ{1,1,1} ,,,,,,分割、DP [n]を[1] = 1の
            IF(N == 1 || == mを1)DPは、[N-] [M] = 1 ; 

            // 場合N == M、2例、DP [N-] [M] 1 + DP = [N-] [1-M。]:
             //   1分割数Mに含まれる場合、mは}唯一{ある
             //   2分割数をmに含まれていない場合、最大値のみM - 1、DP [N-] [M - 1]のための
            他の IF(N-M == )DP [N-] [M] = 1 + DP [N-] [M- 1 ]; 

            // > M n個とき、Mは、[n]は[M最大N、DPを取ることができる ] = DP [n]は[N] 
             IF(N <M)DP [N-] [m]は= DP [N-] [N-]を; 

            // N- <M、2例、DP [n]は[M] = DP [nm]と[M] DP + [N-] [1-M。]:
             //   1 Mに含まれる分割数を、分割数(フロントMを有していてもよい)、最後のMでなければならない{M ........}和= N 、DP [nm]と[M]
             //   2分割数をm、分割することができる最大数に含まれない場合。1-M、DP [N-] [1-M] 
             IF(N> M)DP [n]は[M] DP [N - M] = [M] + DP [n]は[M - 1 ]。
        } 
    } 
} 
int型のmain()
{ 
    INIT(120 )。

    int型のn;
    一方、(CIN >> N){ 
        COUT << DP [n]は[N] << ENDL。
    } 
    戻り 0 
}

 

 -------------------------------------------------- -----------------------------------

今、より複雑なケースのいくつかを考えます

 http://bailian.openjudge.cn/practice/4119?lang=en_US

https://vjudge.net/problem/OpenJ_Bailian-4119

最初のライン:正の整数Kとに分割されるN
異なる正の整数の数とに分割さのNの数:二行
三列:N分割数及び奇数の正の整数の数に分割

特定の実施例:N = 5、K = 2の場合

最初のライン:4 + 1,3 + 2、
二行目:5,4 + 1,3 + 2
行3:1 + 5,1 + 3,1 + 1 + 1 + 1 + 1 + 1

#include <iostreamの>
 使用して 名前空間STD;
 のconst  int型 MAXN = 55 ; 

INT DP1 [MAXN] [MAXN] = { 0 };
 無効 INIT1(INT MAXN)
{ 
    // DP状態設計、DP [N] [k]は、デジタルを表しますnは、数kの組み合わせの数に分割され、0に初期化される
     // の状態遷移を行うことができるように、1は、2つに分割されている場合を含まないパケットの数に数Kは、Kを設定
    するためのINT N- = 1 ; N - <= MAXN; N - ++ ){
         ためINT K = 1 ; K <= MAXN; K ++ ){ 

            // 。Kの1つのみ種類= 1、N- {}
             // 2 N-K =場合のみ、{1,1,1} ,,,,,,
            IF(K == 1 || == NK)DP1 [N-] [k]は= 1 ; 

            // 1.これは、k個の番号1、DPない[NK] [K ] 各桁1.保存数
             @ 2桁1 k番目、DPを有する[N-1] [K-1] ここでは、デジタル1 
            IF(N> K)DP1 [N-] [K] = DP1 [N - K ] [K] + DP1 [N - 1 ] [K - 1 ]; 

            // N- <K 0 
        } 
    } 
} 

int型 INIT2(INT MAXN)
{ 

} 

int型のmain()
{ 
    INIT1(50 ); 

    int型N-、K。
     一方(CIN >> N- K){ 
        COUT << DP1 [N-] [K] <<endl; 
    } 
    戻り 0 
}

 

-------------------------------------------------- -----------------------------------

おすすめ

転載: www.cnblogs.com/taoshiqian/p/11519113.html