LDUOJ —— E. Torre (escolha de dp + estado)

E. Tower


Descrição

Dados os blocos de madeira NN, informa a altura de cada bloco. Você precisa usar esses blocos para construir duas torres da mesma altura. A altura de uma torre é a soma das alturas dos blocos usados ​​para construí-la e de uma torre deve ser pelo menos Use um pedaço de madeira. O bloco de madeira só pode ser usado uma vez ou não. P. Qual é a altura máxima da torre que pode ser construída sob a restrição da mesma altura das duas torres?

Entrada

Na primeira linha, um inteiro NN indica o número de blocos; na segunda linha, NN inteiros indicam a altura do bloco NN.

Resultado

Apenas um número indica a altura da torre mais alta que pode ser construída. Se duas torres da mesma altura não puderem ser construídas, -1 é a saída.

Amostras

Entrada [Copiar] (javascript :)

3
2 3 5

Resultado

5

Dica

N≤50N≤50, a faixa de altura de cada pedaço de madeira é [1.500000] e a altura total de todas as peças de madeira é ≤500000≤500000.

Ideias:

Um dp muito inteligente.
Depois de olhar para as soluções de problemas de outras pessoas, descobri que o nome é a diferença dp (boa alta e
grande ). Suponha que dp [i] [j] represente a altura mais alta da torre alta quando o i-ésimo item é selecionado e o a diferença entre a torre alta e a torre baixa é j.
Em seguida, observe a transferência. Supondo que o estado do primeiro i-1 item tenha sido processado, considere como escolher o i-ésimo item:
1. Se o i-ésimo item não for selecionado, o estado anterior é dp [ i-1] [j]
2. Dê o i-ésimo item para a torre baixa, indicando que a contribuição do i-ésimo item é para reduzir a diferença de a [i], ou seja, o estado anterior é dp [i-1] [j + a [i]]. Por causa da torre baixa, o valor de dp não mudará.
3. Dê o i-ésimo item à torre, indicando que a contribuição do i-ésimo item é aumentar a diferença de a [i], ou seja, o estado anterior é dp [i-1] [ja [eu]]. Devido à torre alta, o valor dp correspondente deve ser alterado. A premissa para a transição efetiva desse estado é j≥a [i].
Pensei neles pela primeira vez, e então pensei.
Na verdade, as três situações acima têm um resultado unificado de que a ordem da torre alta e da torre baixa não é alterada, mas se o i-ésimo item tiver contribuição suficiente, a torre baixa pode se tornar uma torre alta. A seguir, analise a transferência dessa situação:
Suponha que, depois que os primeiros i-1 estados são processados, as alturas das duas pilhas de itens são A e B, respectivamente.
Suponha que em i-1, A seja uma torre alta e B uma torre baixa.
Em i, a altura de B se torna B + a [i], B é uma torre alta e A é uma torre baixa.
Então dp [i] [j] representa B + a [i] -A = j.
Agora considere o estado anterior, i-1: a diferença neste momento é AB, de acordo com a equação da linha anterior, AB = a [i] -j, então o estado anterior é dp [i-1] [a [ eu j].
Então considere a contribuição para o valor dp: a altura da torre alta anterior é A, e a altura da torre alta atual é B + a [i], então a contribuição é j.
Observe que a inicialização e a resposta não existem.

Código:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll>PLL;
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
#define I_int ll
inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
#define read read()
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
ll ksm(ll a,ll b,ll p)
{
    ll res=1;
    while(b)
    {
        if(b&1)res=res*a%p;
        a=a*a%p;
        b>>=1;
    }
    return res;
}
#define PI acos(-1)
const double eps=1e-10;
const int maxn=1e6+100;
int n,dp[55][500010],a[55];
int main()
{
    n=read;
    int sum=0;
    rep(i,1,n)
        a[i]=read,sum+=a[i];
    memset(dp,-0x3f,sizeof dp);
    dp[0][0]=0;
    for(int i=1;i<=n;i++){
        for(int j=0;j<=sum;j++){
            int t=max(dp[i-1][j],dp[i-1][j+a[i]]);///不选第i个,第i个给矮塔
            dp[i][j]=max(t,dp[i][j]);
            if(j>=a[i]){///放在高塔上
                dp[i][j]=max(dp[i][j],dp[i-1][j-a[i]]+a[i]);
            }
            ///第i个给矮塔后 矮塔成为高塔
            if(a[i]>j){
                dp[i][j]=max(dp[i][j],dp[i-1][a[i]-j]+j);
            }
        }
    }
    if(dp[n][0]<=0) puts("-1");
    else printf("%d\n",dp[n][0]);
    return 0;
}

Acho que você gosta

Origin blog.csdn.net/weixin_45675097/article/details/114459166
Recomendado
Clasificación