整数除算 - 間隔DP(砂利合併)

これは、分割するの数ではなく、整数ビットに分割します

タイトル説明

どのように正の整数N(N長<(1部20)M M)に分割>、最大M部分の積となるよう。N、キーボードからのM個の入力、および最大1つの分割方法を出力します。

入力形式

正の整数T(T <= 10000)の最初の行は、データのセットTを発現しました。

次の2行各行Tは正の整数N、M。

出力フォーマット

各テストのために

最大出力の最初の行。

出力分割方式の2行目は、配列は、N個の出力のMの数、スペースによって2つの要素間の開口部の数に分割されます。

サンプル

サンプル入力

1
199 2

サンプル出力

171
19 9

这是递归思想,动态规划是正向的,而判断后是逆向的,输出时运用回溯,达到正向输出的目的
以下是代码
#include <iostreamの> 
する#include <cstdioを> 
する#include <CStringの>
 使用して 名前空間STD、
符号なしのロング ロング T、N- [ 21は、N3 N2] [ 21れる ] [ 21である ]、X、息子[ 1000年 ] [ 1000年 ]、F [ 21は、 [] 21であり ; M] // 最大ため、符号なしのロング整数と
ストリングN1;
 INT printf1(INT A、int型 B)// 出力機能、バックトラック
{
     IF(B == 0戻り 0 ; 
    printf1(息子[A] [B ]、B- 1 )。
    以下のためにint型 I =息子[A] [B] + 1 ; I <= A iが++ 
        COUT << N [i]は、
    裁判所未満 << "  " ; 
} 
int型のmain()
{ 
    CIN >> T。
    int型、L = 1 ; L <= T L ++ 
    { 
        memsetの(nは、0はsizeof (N))。
        memsetの(息子、0はsizeof (息子)); 
        CIN >> N1 >> メートル。
        N2 =n1.length();
        以下のためにint型 i = 0 ; iは= N2 <; Iは++ のためのINT J = 0 ; J <= n2と; jは++ 
            { 
                F [I] [J] = 0 ;
                // N3 [I] [J] = 1。
            }     
        [F 0 ] [ 0 ] = 1 以下のためにint型 i = 1 ; iは= N2 <; iは++ 
        { 
            N [I] = n1の[I- 1 ] - ' 0 ';
            // COUT << N [i]は、
        }
         のためのint型 i = 1 ; iが= N2 <; Iは++ 
        { 
            X = N [i]は、
            int型 J = I; J <= N2; J ++ 
            { 
                N3 [I] [J] =のX。
                X * = 10 
                X + = N [J + 1 ]。
                // coutの<< N3 [I] [J] << " "<< I <<"" << J <<てendl;

        ;私は= N2 <; iは++ 
        { 
            ためint型の J = 1 ; J <= M && J <= I; J ++ 
            { 
                ためのint型のk = 1 ; K <= iは、++ k個
                { 
                    場合(F [I] [J <F [K- 1 ] [J- 1 ] * N3 [K] [I])
                    { 
                        F [I] [J] = F [K- 1 ] [J- 1 ] * N3 [K] [I] ;
                        // coutの<< F [i]の[j]は、
                        息子[I] [J] = K- 1 ; // 记录分割点
                    } 
                    
                } 
            } 
        } 
        COUT << [N2] [M] << F ENDL。
        もし(M == N2)// 特判、防止输出紊乱
            ためINT i = 1 ; iは= N2 <; iは++ 
                COUT << N [I] << "  " printf1(N、M)。
        coutの << てendl; 
    } 
}

 

 石子合并

タイトル説明

円形の石の周りの遊び場は、新しいパイル及び石の新しい山に石パイルにマージするために有することである。各時間だけ所定の選択された隣接スタック2、Nを配置積ま番号、複合スコアことを覚えておいてください。

テストスタック最大複合スコアに重ねN石を計算するアルゴリズムを設計します。

入力形式

第1データ線試験の正の整数N、1≤N≤2000、N石が発現重ね。第二行は、それぞれ、数Nを有し、石の各山の数を表します。

出力フォーマット

出力コモンライン1、最大スコア

サンプル

サンプル入力

4
4 4 5 9

サンプル出力

54
最终一堆一定是前一次合并后,剩下的两堆相加的最优解。

状態遷移方程式
設けT [I、J]は石のj数の和にスタックからi番目のスタックを示しています。
Fmaxの(i、j)は石のJ-ヒープの最大スコアに合併から石のiヒープを表し
Fminを(i、j)が(質問の意味を参照してください石のjヒープの合計最小スコアから石のiヒープを表し、必須ではありません)

 

附上代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m[4001],m1[4001][4001],f[4001][4001],x,ma;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>m[i];
    }
    for(int i=1;i<=n;i++)
    {
        m[i+n]=m[i];
    }
    for(int i=1;i<=2*n-1;i++)
    {
        x=m[i];
        for(int j=i+1;j<=2*n-1;j++)
        {
            x+=m[j];
            m1[i][j]=x;
        }
    }
    for(int i=2*n-1;i>=1;i--)
    {
        for(int j=i;j<=2*n-1;j++)
        {
            f[i][j]=max(f[i+1][j],f[i][j-1])+m1[i][j];
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(ma<f[i][i+n-1])ma=f[i][i+n-1];
    }
    cout<<ma;
}

 




 

 

 

おすすめ

転載: www.cnblogs.com/fengwu2005/p/11274738.html