Динамическое программирование (2) - Общие Динамическая модель программирования

\ (1 \) цифровой треугольник

Каждый раз, когда нижний левый или правый нижний угол может пойти сетку, ища путь максимального веса.

\ (Д (I, J) = тах (г (г + 1, J), D (I + 1, J + 1)) + а (I, J). \) Граница \ (D (п + 1 , J) = 0 \) , толкнул снизу вверх (потому что для обеспечения \ (я + 1 \) линия раздела \ (I \) перед обновлением OK)

for(int i=1;i<=n+1;++i) d[n+1][i]=0;
for(int i=n;i>=1;--i)
{
    for(int j=1;j<=i;++j)
    {
        d[i][j]=max(d[i+1][j],d[i+1][j+1])+a[i][j];
    }
}

\ (2 \) вложенных прямоугольников

Там \ (п \) прямоугольники, каждый прямоугольник с кортежем \ ((а, Ь) \ ) фиг. Мы предопределили прямоугольную \ (X (A, B) \) могут быть вложены в прямоугольнике \ (У (в, г) \) , если и только если \ (А <С, В <D \) или \ (б < С, а <D \) (повернутый \ (\ 90) градусов). Выбор , как многие прямоугольник расположен так , что , кроме последней, может быть вложена в пределах каждого прямоугольника нижней прямоугольника. Если несколько решений, как можно меньше, чтобы обеспечить лексикографические

\ (DAG \) длинная дорога проблема

//dp[i]表示的是从i点出发的最长路
int dp(int x)
{
    int &ans=d[x];
    if(ans) return ans;
    for(int i=1;i<=n;++i)
    {
        if(G[x][i])
        {
            ans=max(ans,dp(i)+1);//注意记录的是从终点到起点的距离,这是为了方便字典序最小方案的输出
        }
    }
    d[x]=ans;
    return ans;
}
void print(int i)
{
    printf("%d ",i);
    for(int j=1;j<=n;++j)
    {
        if(G[i][j]&&d[j]+1==d[i])
        {
            print(j);
        }
    }
}


for(int i=1;i<=n;++i)
{
    scanf("%d%d",&a[i],&b[i]);
    if(a[i]>b[i]) swap(a[i],b[i]);
}
for(int i=1;i<=n;++i)
{
    for(int j=1;j<=n;++j)
    {
        if(a[i]>a[j]&b[i]>b[j])
        {
            G[j][i]=1;
        }
    }
}
int Max=0;
int endpos;
for(int i=1;i<=n;++i)
{
    if(dp(i)>Max)
    {
        Max=dp[i];
        endpos=i;
    }
}
print(endpos);

\ (3 \) чеканки монеты

\ [F (I) = мин (инф, е [I-VI] + 1 | Vi <= я), г (я) = макс (-inf, г [I-VI] + 1 | Vi <= я) (монетные номиналы Vi) \]

\ (4,01 \) Рюкзак имеет особую тему подробно объяснить

\ (5 \) задачи множество точек соответствия (например , давление \ (ДП \) )

\ (Г (S) \) представляет собой набор \ (\ S) кратчайшего расстояния после спаривания

double dis(int i,int j)
{
    return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;++i) scanf("%d%d",&a[i].x,&a[i].y);
    memset(d,0x7f,sizeof(d));
    d[0]=0;
    for(int i=1;i<(1<<n);++i)//由于第一个点无论如何都是要配对的,所以无需枚举(否则时间复杂度会
    {                        //乘上一个n)
        int k=0;
        while(!(i&(1<<k))) ++k;
        for(int j=k+1;j<n;++j)
        {
            if(i&(1<<j)) d[i]=min(d[i],d[i^(1<<k)^(1<<j)]+dis(k,j));
        }
    }
}

\ (6 \) длинная проблема подпоследовательности поднимается \ ((LIS) \)

Первичная: \ (O (п ^ 2) \) (но не слишком хорошо, и я узнал , во - вторых, они никогда не использовали его)

Дополнительно: \ (О (NlogN) \) \ (D [I] , \) , представленное \ (а [я] \) длина самых длинных суб-последовательностей восходящего конца

for(int i=1;i<=n;+i) g[i]=inf;
for(int i=0;i<n;++i)
{
    int k=lower_bound(g+1,g+n+1,a[i])-g;
    d[i]=k;
    g[k]=a[i];
}

\ (7 \) длинная общая проблема подпоследовательность \ ((ЛВП) \) [Примечание: \ (ЛВП \) иногда называют как самый длинный общий суффикс, и \ (ЖКП \) длинный общий префикс соответствуют]

for(int i=0;i<la;++i)
{
    for(int j=0;j<lb;++j)
    {
        if(a[i]==b[j])
        {
            d[i][j]=max(d[i][j],d[i-1][j-1]+1);
        }
        else if(a[i]!=b[j])
        {
            d[i][j]=max(d[i-1][j],d[i][j-1]);
        }
    }
}

Вы также можете пролистать оптимизации массива

int f=0;
for(int i=0;i<la;++i)
{
    f^=1;
    for(int j=0;j<lb;++j)
    {
        if(a[i]==b[j])
        {
            d[f][j]=max(d[f][j],[f^1][j-1]+1);
        }
        else if(a[i]!=b[j])
        {
            d[f][j]=max(d[f^1][j],d[f][j-1]);
        }
    }
}

\ (8 \) Максимальная непрерывная и

Приставка и практика:

for(int i=1;i<=n;++i)
{
    scanf("%d",&a[i]);
    sum[i]=sum[i-1]+a[i];
}
int Maxn=sum[n],Max=0;
for(int i=n-1;i>=1;--i)
{
    Max=max(Max,Maxn-sum[i]);
    Maxn=max(Maxn,sum[i]);
}

Динамические методы программирования: \ (D [я] \) представляет собой максимальное непрерывное окончание и я

for(int i=1;i<=n;++i) scanf("%d",&a[i]);
for(int i=1;i<=n;++i)
{
    d[i]=max(0,d[i-1])+a[i];
}

рекомендация

отwww.cnblogs.com/iwillenter-top1/p/11828239.html