10/17学习总结

本文探讨了图的两种存储方式:邻接矩阵和链式前向量,重点介绍了链式前向量在节省空间方面的优势。同时,通过两个实际的动态规划问题——石子合并和最长递增子序列,展示了如何运用动态规划解决问题。代码示例详细解释了如何实现这些算法,以优化内存使用和提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

图的存储
首先是我们都了解的邻接矩阵,可用来储存边与边之间的距离,但问题也是很明显的。他太浪费空间了,且复杂度还是n的平方,很明显这个是非常不划算的,这里就可以用链式前向量来储存。

const int num=1000005;
struct edge{
int to,next,w;}e[num];
int cnt;
void init()
{
    for(int i-0;i<num;i++)
    {
        e[i].next=-1;
        head[i]=-1;
    }
    cnt=0;
}
void adddedge(int u,int v,int w)
{
    edge[cnt].to=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}

一些dp的题目

在这里插入图片描述

#include<bits/stdc++.h>

using namespace std;
const int maxn = 150;
const int maxl = 300 * 105;
//其实开90 * 105就可以了;
int L,s,t,m,ss[maxn],a[maxn],dp[maxl],base;
//stone就是石头的初始位置;a为我们将石头初始化后的石头位置;
bool v[maxl];
//标记一下坐标上的该点是否为石头;
int main()
{
    int l,s,t,m;
    cin>>l>>s>>t>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>ss[i];
    }
    sort(ss+1,ss+1+m);
    int b=s*t;
    if(s==t)
    {
        int c=0;
        for(int i=1;i<=m;i++)
        {
         if(ss[i]%s==0)
            c++;
        }
         cout<<c<<endl;
    }
    else
    {
        for(int i=1;i<=m;i++)
    {
            int t=ss[i]-ss[i-1];
            if(t>=b)
            t=b;
            a[i]=a[i-1]+t;
            v[a[i]]=1;
    }
    l=a[m]+b;
        memset(dp,0x7f,sizeof(dp));
        dp[0]=0;
        for(int i=1;i<=l;i++)
        {
            for(int j=s;j<=t;j++)
            {
                if(i-j>=0)
                {
                        if(v[i])
                    {
                        dp[i]=min(dp[i],dp[i-j]+1);

                    }
                    else
                    dp[i]=min(dp[i],dp[i-j]);

                }
            }
        }
        int minn=9999999;
        for(int i=a[m];i<=l;i++)
        {
            minn=min(minn,dp[i]);
        }
        cout<<minn<<endl;
    }
  	return 0;
}

在这里插入图片描述
类似石子合并,根据题意来更改dp就ok了

#include <iostream>
using namespace std;
int a[100000];
int dp[10000][10000];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        a[i+n]=a[i];
    }
    for(int i=1;i<=2*n;i++)
    dp[i][i]=0;

    for(int len=2;len<=n;len++)
    {
        for(int i=1;i<=2*n-len+1;i++)
        {
            int j=i+len-1;
            for(int k=i;k<=j-1;k++)
            {
                dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+a[i]*a[k+1]*a[j+1]);
            }
        }
    }
     int ans=0;
    for (int i=1;i<=n;i++)
    {
        ans=max(dp[i][i+n-1],ans);
    }
    cout<<ans<<endl;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值