首页 > 代码库 > 两个区间dp的题目 奇怪二叉树和卡牌游戏

两个区间dp的题目 奇怪二叉树和卡牌游戏

技术分享

技术分享

技术分享

#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
int n,a[35],dp[35][35],root[35][35];
int num=1;
void print(int l,int r)
{
    if(l>r) return;
    int ro=root[l][r];
    if(num++<n)
        printf("%d ",ro);
    else
        printf("%d",ro);
    print(l,ro-1);
    print(ro+1,r);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        dp[i][i]=a[i];
        root[i][i]=i;
    }
    for(int l=2;l<=n;l++)
    {
        for(int i=1;i+l-1<=n;i++)
        {
            int j=i+l-1;
            for(int k=i;k<=j;k++)
            {
                if(k==i&&k!=j)
                {
                    if(dp[i][j]<dp[k+1][j]+a[i])
                    {
                        dp[i][j]=dp[k+1][j]+a[i];
                        root[i][j]=k;
                    }
                }
                if(k==j&&k!=i)
                {
                    if(dp[i][j]<dp[i][k-1]+a[j])
                    {
                        dp[i][j]=dp[i][k-1]+a[j];
                        root[i][j]=k;
                    }
                }
                if(k!=i&&k!=j&&dp[i][j]<dp[i][k-1]*dp[k+1][j]+a[k])
                {
                    dp[i][j]=dp[i][k-1]*dp[k+1][j]+a[k];
                    root[i][j]=k;
                }
            }
        }
    }
    printf("%d\n",dp[1][n]);
    print(1,n);
    return 0;
}

 

技术分享

技术分享

#include<iostream>
#include<stdio.h>
#include<memory.h>
#define MAX 0x3f3f3f3f
using namespace std;
int num[105];
int dp[105][105];
int n;
int main()
{
    memset(dp,MAX,sizeof(dp));
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
        scanf("%d",&num[i]);

    for(int i=2; i<=n-1; i++)
    {
        dp[i-1][i+1]=num[i-1]*num[i]*num[i+1];
    }

    //dp[i][j]代表抽取i-j区间的最小值
    for(int k=3; k<=n; k++)
    {
        for(int i=1; i+k<=n; i++)
        {
            int j=i+k;
            //关键点:枚举最后抽取的牌
            for(int e=i+1; e<=j-1; e++)
            {
                //最左边的牌
                if(e==i+1)
                    dp[i][j]=min(dp[i+1][j]+num[i]*num[i+1]*num[j],dp[i][j]);
                //最右边的牌
                else if(e==j-1)
                    dp[i][j]=min(dp[i][j-1]+num[i]*num[j-1]*num[j],dp[i][j]);
                //中间的牌
                else
                    dp[i][j]=min(dp[i][e]+dp[e][j]+num[i]*num[e]*num[j],dp[i][j]);
            }
        }
    }
    printf("%d",dp[1][n]);
    return 0;
}

 

两个区间dp的题目 奇怪二叉树和卡牌游戏