정수 나눗셈 - 간격 DP (자갈 합병)

이는가로 나눌 수 없지만 정수 비트 분할

제목 설명

방법 <(1 부분 M M)로 나눈 값 ((20)은 양의 정수 N N 길이)> 최대 M 부 생성물되도록. N, M, 키보드로부터 입력 한 최대 하나의 분할 방식으로 출력한다.

입력 형식

양의 정수이고 T의 첫번째 행 (T는 <= 10000), T의 데이터 세트를 표시.

다음 두 라인을 각 행 T 양의 정수 N, M.

출력 형식

각 시험

최대 출력의 첫 번째 줄.

출력 분할 방식의 두 번째 줄은 서열 N 출력의 M 번호 공백으로 두 요소들 사이의 개구부로 분할된다.

견본

샘플 입력

1
199 2

샘플 출력

171
19 9

这是递归思想,动态规划是正向的,而判断后是逆向的,输出时运用回溯,达到正向输出的目的
以下是代码
#INCLUDE <iostream> 
#INCLUDE <cstdio> 
#INCLUDE <CString을>
 은 USING  공간 STD, 
부호   T, N- [ 21이고 , N2는 N3 [ 21이다 ] (21)은 , X, 인자 [ 1000 ] [ 1000 ], F [ 21이다 ] [ 21이고 , m]; // 부호 길이의 정수와 최대위한 
문자열 N1;
 INT printf1 ( INT A, INT의 B) // 출력 기능 되돌아 
{
     IF (B의 == 0 ) 복귀  0 ; 
    printf1 (SON [A] [B ] B- 1 );
    위한 ( int로 I = 아들 [A] [B] + 1 ; I <= A; 내가 ++ ) 
        COUT << N [I]; 
    COUT << "  " ; 
} 
INT 의 main () 
{ 
    CIN >> t;
     ( INT의 L = 1 , L <= t; L ++ ) 
    { 
        memset 함수 (N, 0 , 는 sizeof (N)); 
        memset 함수 (아들, 0 , sizeof 연산자 (아들)); 
        CIN >> >> N1 m; 
        N2 =n1.length ();
        위한 ( int로 I = 0 ; I는 N2 = <; 나는 ++ )
              ( INT J = 0 ; J <=의 N2, J를 ++ ) 
            { 
                F [I] [J] = 0 ;
                // N3 [I] [J] = 1; 
            }     
        F를 [ 0 ] [ 0 ] = 1 ;
        위한 ( int로 I = 1 ; i가 = <N2; 내가 ++ ) 
        { 
            N [I] = (N1)에 [I- 1 ] - ' 0 ';
            // COUT << N [I]; 
        }
         에 대해 ( int로 I = 1 ; i가 = <N2; 내가 ++ ) 
        { 
            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 <; 내가 ++ ) 
        { 
            위해 ( INT의 J = 1 ; J <= m && J <= I, J ++ ) 
            { 
                 ( INT에 K = 1 ; 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; 내가 ++ ) 
                COUT << N [] << "  " ;
        다른 printf1 (N2, m); 
        COUT << ENDL; 
    } 
}

 

 石子合并

제목 설명

원형 돌 주위 놀이터 N은 돌 더미로 통합하기 위해,이 위치하는 쌓여.마다 단지 소정의 선택된 인접 스택 (2) 새로운 돌 더미의 더미로 새로운 숫자가 결합 된 점수 기억 해요.

테스트 스택 최대 결합 점수로 쌓여 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