zoukankan      html  css  js  c++  java
  • 1570:【例 2】能量项链

    思路:

    很简单的区间dp,注意最外层循环设置成(当前合并区间长度)和(当前合并次数)之间的差异

    代码:(当前合并的区间长度)

    ```cpp #include #define ll long long #define maxn 2050

    using namespace std;

    struct node{
    ll l,r;
    }a[maxn];
    ll f[maxn][maxn],n;
    //2 3 5 10 2 3 5 10
    int main()
    {
    memset(f,0,sizeof(f));
    cin>>n;
    for(int i=1;i<=n;i++)
    {
    cin>>a[i].l ;
    a[i-1].r =a[i].l ;
    a[i+n].l =a[i].l ;
    a[i+n-1].r =a[i].l ;
    }

    a[2*n].r =a[1].l ;
    

    // for(int i=1;i<=2n;i++) cout<<a[i].l <<" "<<a[i].r <<' ';
    for(int l=2;l<=n;l++)//枚举区间长度
    {
    for(int i=1;i+l-1<=2
    n;i++)
    {
    int j=i+l-1;
    for(int k=i;k<j;k++)
    {
    f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+a[i].l*a[k].r *a[j].r);
    // cout<<i<<" "<<j<<" "<<k<<" "<<f[i][j]<<" "<<f[i][k]<<" "<<f[k+1][j]<<" "<<a[k].l <<" "<<a[k].r <<" "<<a[k+1].r <<' ';
    }
    }
    }

    ll ans=0;
    /*
    for(int i=1;i<=2*n;i++)
    {
    
    	for(int j=1;j<=2*n;j++)
    	{
    		cout<<f[i][j]<<" ";
    	}
    	cout<<'
    ';
    }*/
    
    for(int i=1;i<=n;i++)
    {
    	ans=max(ans,f[i][i+n-1]);
     } 
     
     cout<<ans<<'
    ';
     return 0;
    

    }

    
    (当前合并次数):
    ```cpp
    #include <cstdio> 
    #include <cstring> 
    #include <iostream> 
    using namespace std; 
    int f[210][210]; 
    struct node 
    { 
        int x,y; //头标记和尾标记
    }a[210]; 
    int main() 
    { 
        int n; 
        scanf("%d",&n); 
        for (int i=1;i<=n;i++) 
        { 
            scanf("%d",&a[i].x); 
            a[i-1].y=a[i].x; //前一个珠子的尾标记等于后一个珠子的头标记
        } 
        a[n].y=a[1].x; //注意是环!收尾相连
        for (int i=1;i<n;i++) 
            a[i+n]=a[i]; //复制一段在后边,那么从i~i+n就是看成是一个从i开始的一条线了,省了一条循环
        memset(f,0,sizeof(f)); //赋0
        //f[i][j]:合并第i~j个珠子时的最优情况
        for (int k=1;k<=n;k++) //枚举长度(与合并石子的x相似)
        { 
            for (int i=1;i<2*n-k;i++) //从第i个石子开始断,,那么从i~i+n就是一条线
            { 
                for (int j=i;j<i+k;j++) //在i~i+k中选一个点j分成i~j和j+1~i+k两段(与合并石子的k相同)
                { 
                    f[i][i+k]=max(f[i][i+k],f[i][j]+f[j+1][i+k]+a[i].x*a[j].y*a[i+k].y); //计算能量
                } 
            } 
        } 
        int ans=0; 
        for (int i=1;i<=n;i++) 
        { 
            ans=max(f[i][i+n-1],ans); 
            //扫一遍,看看从哪里断得到的值最大
        } 
        
        for(int i=1;i<=2*n;i++)
        {
        	for(int j=1;j<=2*n;j++) cout<<f[i][j]<<" ";
    		cout<<'
    '; 
    	}
        printf("%d",ans); 
        return 0; 
    } 
    
    
  • 相关阅读:
    线性代数基础知识的复习
    第一个机器学习算法:线性回归与梯度下降
    初识机器学习
    VScode中LeetCode插件无法登录的情况
    内存管理-内存管理功能
    分组密码
    Linux进程调度
    进程调度
    死锁
    临界区和缩
  • 原文地址:https://www.cnblogs.com/yxr001002/p/14445075.html
Copyright © 2011-2022 走看看