[] Projeto e análise de dinâmica de programação Capítulo IV Algorithm

A idéia básica da programação dinâmica

  • algoritmo de programação dinâmica é comumente usado para resolver problemas com alguns dos melhores propriedades. Em tais assuntos, pode haver muitas soluções viáveis. Cada solução corresponde a um valor, esperamos encontrar uma solução com o valor ideal.
  • A idéia básica é a de resolver o problema será dividido em vários sub-perguntas, a primeira solução de sub-problema, a solução do problema original e a solução obtida a partir destes sub-temas.
  • Adequado sub para resolver problemas de programação dinâmica, o problema muitas vezes é decompostoNão independentes um do outro. Muitos problemas se o número de crianças com um método de dividir e conquistar para resolver este problema, a decomposição de alguns sub-problemas foram contados duas vezes muitas vezes.
  • Se pudermos salvar a criança a resposta para o problema foi resolvido, e na necessidade de descobrir as respostas foram obtidas, assim você pode evitar um monte de dupla contagem, economizar tempo. Podemos usar uma tabela para gravar as respostas para todas as sub-problemas têm solução. Se está sendo utilizado no futuro, independentemente das sub-problemas, enquanto calcula-se que ele irá preencher na tabela de resultados.

Passo Programação Projeto Dinâmica

  1. Propriedades encontrar a solução ideal, e para caracterizar a estrutura em que;
  2. Definida recursivamente o valor óptimo (equação de programação dinâmico escrito);
  3. De forma bottom-up calcular o valor ideal;
  4. A informação obtida quando o cálculo de um valor óptimo construir uma solução óptima.

ps: Etapas 1 a 3 são os passos básicos do algoritmo de programação dinâmica. No caso de um valor ideal requer apenas, passo 4, podem ser omitidos; Para uma solução óptima para o problema exige, passo 4 deve ser realizada.

Características problema de programação dinâmica

A eficácia do algoritmo de programação dinâmica depende de dois natureza importante do problema em si tem:
ideal subestrutura:
Quando a solução ideal contém solução ideal para o problema de seu filho, disse que o problema tem sub-óptima estrutural.
Sobreposição de sub-problemas :
quando um top-down recursiva do algoritmo Solutions, cada sub-problema nem sempre são produzidos novos problemas, alguns sub-problemas são de iterações. algoritmo de programação dinâmica é o uso da natureza sobreposição deste sub-problemas, a solução apenas uma vez para cada sub-problema, e sua solução irá salvar uma tabela, após a solução desses sub-problemas utilizando, tanto quanto possível.

Alguns exemplos típicos

Um problema ainda a multiplicação de matrizes
[Problema]
n matriz Dado {A1, A2, ..., An }, em que Ai e Ai + 1 é multiplicativo, i = 1,2 ..., N- 1. Como determinar o cálculo da matriz de cálculo até mesmo encomendar o produto, tornando o produto ainda nesta ordem da multiplicação de matrizes para calcular o número mínimo exigido?
[Análise]
O produto de matriz ainda AiAi + 1 Aj ... abreviado como A [i: j], onde i≤j; Um cálculo investigado [1: N] ordem óptimo calculado.
Esta sequência é fornecida entre as matrizes calculados Ak e Ak + 1 cadeia matriz é quebrado, 1≤k <n, o modo correspondente está completamente suportado (A1A2 ... Ak) (Ak + 1Ak + 2 ... An).
Um cálculo: melhor ordem de [1 n] está incluído na filha do Fio Calculada matriz A [1: k] e A [k + 1: n] é a melhor ordem.
Cálculo: A [1: k] quantidade calculada além Um [k + 1: N] de cálculo, A? [1: k] Plus e uma [K + 1: n] é calculado multiplicando-se a quantidade de
[método]
desenho do estudo a [i: j], 1≤i≤j≤n , mais por um pequeno número de vezes m [i, j] requerido, o valor óptimo do problema original m [1, n]
quando i quando j =, a [i: j] = Ai, e, por conseguinte, m [i, i] = 0, i = 1,2, ..., n
ao i <j, a
Aqui Insert Picture Descrição
pode ser definida recursivamente m [i, j] é :
Aqui Insert Picture Descrição
[] complexidade vez O ( n 2 ) O (n ^ 2)
[Código]

#include<bits/stdc++.h>
using namespace std;
#define NUM 51
int p[NUM],n;
int m[NUM][NUM];
int s[NUM][NUM];
int main()
{
    cin>>n;
    for(int i=0; i<=n; i++)
        cin>>p[i];
    for(int r=2; r<=n; r++)
        for(int i=1; i<=n-r+1; i++)
        {
            int j=i+r-1;//计算初值,从i处断开
            m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];
            s[i][j] = i;
            for(int k=i+1; k<j; k++)
            {
                int t = m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
                if (t < m[i][j])
                {
                    m[i][j] = t;
                    s[i][j] = k;
                }
            }
        }
    cout<<m[1][n]<<endl;
    return 0;
}

algoritmo recursivo:

int Recurve(int i, int j)
{
    if(i==j)
        return 0;
    int u=Recurve(i, i)+Recurve(i+1,j)+p[i-1]*p[i]*p[j];
    s[i][j]=i;
    for(int k=i+1; k<j; k++)
    {
        int t=Recurve(i, k)+Recurve(k+1,j)+p[i-1]*p[k]*p[j];
        if (t<u)
        {
            u=t;
            s[i][j]=k;
        }
    }
    m[i][j]=u;
    return u;
}

Memorando de algoritmos:
algoritmo de programação dinâmica como memorando maneira de salvar a criança responde perguntas foram resolvidos com uma mesa, quando nos deparamos com a criança problema, simplesmente para encontrar respostas para as sub-problemas, sem ter que resolvido.

int LookupChai  (int i, int j)
{
    if(m[i][j]>0)
        return m[i][j];
    if(i==j)
        return 0;
    int u=LookupChain(i,i)+LookupChain(i+1,j)+p[i-1]*p[i]*p[j];
    s[i][j]=i;
    for(int k=i+1; k<j; k++)
    {
        int t=LookupChain(i,k)+LookupChain(k+1,j)+p[i-1]*p[k]*p[j];
        if (t<u)
        {
            u=t;
            s[i][j]=k;
        }
    }
    m[i][j] = u;
    return u;
}

Em segundo lugar, o mais longo subsequência comum
[Problema]
Se uma dada sequência X = {x1, x2, ... ,} xm, em seguida, uma outra sequência Z = {z1, z2, ... , zk}, X é uma subsequência refere-se à presença o subscrito uma sequência estritamente crescente {I1, I2, ..., ik } de tal modo que para todos os j = 1,2, ..., k têm: zj = xij.
Dadas duas sequências X e Y, Z, quando a subsequência outra sequência de ambos X e Y é uma subsequência de tempo, que o referido Z é uma sequência de X e Y subsequência comum .
Dadas duas sequências X = {x1, x2, ... , xm} e Y = {y1, y2, ... , yn}, para encontrar o mais longo subsequência comum de X e Y são. E a saída dessa sequência.
[Análise]
reinicialização sequência X = {x1, x2, ... , xm} e Y = {y1, y2, ... , yn} é a mais longa comum subsequência Z = {z1, z2, ... , z k}, em seguida,
1) Se xm = yn, em seguida, zk = XM = yn, e ZK-1 xm-1 é a mais longa soma comum subsequência yn-1.
2) Se o xm ≠ yn e ZK ≠ xm, então Z é o mais longo subsequência comum XM-1 e Y.
3) Se o xm ≠ yn yn e ZK ≠, então Z e X in-1 é a subsequência comum mais longo.
A saber:
Aqui Insert Picture Descrição
[code]

#include<bits/stdc++.h>
using namespace std;
int n,m;
char a[10010],b[10010];
int dp[10010][10010],x[10010][10010];
vector<char>v;

void LCS(int i,int j)
{
    if(i==0||j==0)
        return;
    if(x[i][j]==1)
    {
        LCS(i-1,j-1);
        v.push_back(a[i]);
    }
    else if (x[i][j]==2)
        LCS(i-1,j);
    else
        LCS(i,j-1);
}

int main()
{
    cin>>n>>m;
    for(int i=1; i<=n; i++)
        cin>>a[i];
    for(int i=1; i<=m; i++)
        cin>>b[i];
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if(a[i]==b[j])
            {
                dp[i][j]=dp[i-1][j-1]+1;
                x[i][j]=1;
            }
            else if (dp[i-1][j]>=dp[i][j-1])
            {
                dp[i][j]=dp[i-1][j];
                x[i][j]=2;
            }
            else
            {
                dp[i][j]=dp[i][j-1];
                x[i][j]=3;
            }
        }
    }
    cout<<dp[n][m]<<endl;
    LCS(n,m);
    for(int i=v.size()-1;i>=0;i--)
        cout<<v[i]<<" ";
    cout<<endl;
    return 0;
}

Em terceiro lugar, o sub-segmento e o máximo
[problemas]
a uma sequência determinada pelo a1 n inteiros (incluindo números inteiros negativos) que consiste em, A2, ..., An, seleccionando o valor máximo e a sequência de sub-segmentos.
Defina seu maior sub-segmento quando todos são inteiros negativos e zero.
Os valores ideais requeridos:
Aqui Insert Picture Descrição
[Análise]
bj é a maior posição sub-segmento e j a 1:
Aqui Insert Picture Descrição
fácil saber definido por bj, se bj-1> 0 quando bj = bj-1 + aj, caso contrário bj = aj.
Bj é calculado recursão de programação dinâmica: bj = max {bj-1 + AJ, AJ}, 1≤j≤n.

[Código]

#include<bits/stdc++.h>
using namespace std;

int n,a[100010];
int b,sum,l,r,s;

int main()
{
    cin>>n;
    for(int i=1; i<=n; i++)
        cin>>a[i];
    for(int i=1; i<=n; i++)
    {
        if(b>0)
            b+=a[i];
        else{
            b=a[i];
            s=i;
        }
        if(b>sum)
        {
            sum=b;
            r=i;
            l=s;
        }
    }
    cout<<l<<" "<<r<<" "<<sum<<endl;
    return 0;
}

Em quarto lugar, o problema da mochila 0-1
[Problema]
Dado um conjunto de itens s = {1,2,3, ..., n }, o peso do item i wi é, o valor é VI, capacidade mochila de W, isto é, a carga máxima pesando não mais de W. Dentro de um total limitado W peso, como podemos escolher itens, a fim de fazer o valor máximo total dos itens.
Se o item não pode ser dividida, isto é, quer o artigo inteiro i ao seleccionar ou não seleccionar; artigo i dentro de um saco não pode ser repetidamente, apenas uma parte do artigo não pode ser carregada com i, em seguida, o problema é chamado 0-1 problema da mochila.
Se o item pode ser dividido, então o problema é chamado problema da mochila, algoritmo guloso adequado para uso.
[Análise]
i≤k≤n valor ideal de p (i, j).
Mochila capacidade j, é um item opcional i, i + 1, ..., n o valor ideal quando o problema 0-1 mochila.
Aqui Insert Picture Descrição
Aqui Insert Picture Descrição
Aqui Insert Picture Descrição
[Código]

#include<bits/stdc++.h>
using namespace std;
int n,m;
int f[100010],w[100010],v[100010];
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>w[i]>>v[i];
    memset(f,0,sizeof(f));
    f[0]=0;
    for(int i=1; i<=n; i++)
        for(int j=m; j>=w[i]; j--)
            f[j]=max(f[j],f[j-w[i]]+v[i]);
    int ans=0;
    for(int j=0; j<=m; j++)
        ans=max(ans,f[j]);
    cout<<ans<<endl;
    return 0;
}
Publicado 335 artigos originais · ganhou elogios 110 · vê 20000 +

Acho que você gosta

Origin blog.csdn.net/weixin_43460224/article/details/105095233
Recomendado
Clasificación