动态规划(线性)

898. 数字三角形

https://www.acwing.com/problem/content/900/

 

 
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=510,INF=1e9;
int n;int a[N][N],p[N][N];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=i;j++)
            cin>>a[i][j];
    //初始化,便于后面更新
    memset(p,-0x3f3f3f3f,sizeof p);
    //切记头一个初始化
    p[1][1]=a[1][1];
    
    for(int i=2;i<=n;i++)
        for(int j=1;j<=i;j++)
            p[i][j]=max(p[i-1][j-1]+a[i][j],p[i-1][j]+a[i][j]);
    //最大值在最后一排,但不一定是最后一个,需要求解
    int res=-INF;
    for(int i=1;i<=n;i++) res=max(res,p[n][i]);
    cout<<res<<endl;
    
    return 0;
}

 最长子序列

https://www.acwing.com/problem/content/897/

(可以不相邻取子串)

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int n;int a[N],p[N];
int main()
{
   cin>>n;
   for(int i=1;i<=n;i++)
    cin>>a[i];
    
    for(int i=1;i<=n;i++)
    {
        p[i]=1;//只有a[i]一个数
        for(int j=1;j<i;j++)
        {
            if(a[j]<a[i]) p[i]=max(p[i],p[j]+1);
        }
    }
    
    int ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,p[i]);
    
    cout<<ans<<endl;
    return 0;
}
//贪心求法
#include<iostream>
using namespace std;
const int N=100010;
int a[N],p[N];int n;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int len=1;p[1]=a[1];
    for(int i=2;i<=n;i++) 
    {
        int l=0,r=len;//二分找到位置
        while(l<r){
            int mid=l+r+1>>1;
            if(p[mid]<a[i]) l=mid;
            else r=mid-1;
        }
        len=max(len,r+1);//更新最大长度
        p[r+1]=a[i];//长度增加,下一个位置的最小值变化,因为更新的数肯定小于下一个值
    }
    cout<<len<<endl;
    return 0;
}

 

求路径

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int n;int a[N],p[N],s[N];
int main()
{
   cin>>n;
   for(int i=1;i<=n;i++)
    cin>>a[i];
    
    for(int i=1;i<=n;i++)
    {
        p[i]=1;//只有a[i]一个数
        s[i]=0;
        for(int j=1;j<i;j++)
        {
            if(a[j]<a[i]) {
                if(p[j]+1>p[i])
                {
                    p[i]=p[j]+1;
                    s[i]=j;//记录上一个位置的下标
                }
            }
        }
    }
    
    int ans=0;int k;
    for(int i=1;i<=n;i++){
        if(p[i]>ans){
        ans=p[i];
        k=i;
        }
    } 
    
    cout<<ans<<endl;
    
    for(int i=k;i!=0;i=s[i])//倒叙遍历输出
        cout<<a[i]<<" ";
        
    return 0;
}

最长公共子序列(字符串)

https://www.acwing.com/problem/content/899/

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
char a[N],b[N];
int p[N][N];
int n,m;
int main()
{
    cin>>n>>m;
    scanf("%s%s", a+1, b+1);
    
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            p[i][j]=max(p[i-1][j],p[i][j-1]);
            if(a[i]==b[j]) p[i][j]=max(p[i][j],p[i-1][j-1]+1);
        }
    }
        
    cout<<p[n][m]<<endl;
            
    return 0;
}

 分组DP

https://www.acwing.com/problem/content/284/

#include<iostream>
using namespace std;
const int N=1010;
int sum[N];int a[N];int p[N][N];
int main()
{
    int n;cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
    for(int len=2;len<=n;len++){//区间长度
        for(int i=1;i+len-1<=n;i++){//枚举区间开头
            int j=i+len-1;//区间结尾
            p[i][j]=1e9+10;
            for(int k=i;k<j;k++)//区间内不同分段
            {
                p[i][j]=min(p[i][j],p[i][k]+p[k+1][j]+sum[j]-sum[i-1]);
            }
        }
    }
    cout<<p[1][n]<<endl;
    return 0;
}

 

最短编辑距离

https://www.acwing.com/problem/content/904/

 

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1010;
int n,m;char a[N],b[N];
int f[N][N];
int main()
{
    scanf("%d%s",&n,a+1);
    scanf("%d%s",&m,b+1);
    //因为存在i-1等操作,所以必须初始化0的位置
    for(int i=0;i<=m;i++) f[0][i]=i;
    for(int j=0;j<=n;j++) f[j][0]=j;
    
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            f[i][j]=min(f[i-1][j]+1,f[i][j-1]+1);
            if(a[i]==b[j]) f[i][j]=min(f[i][j],f[i-1][j-1]);
            else f[i][j]=min(f[i][j],f[i-1][j-1]+1);
        }
        
    cout<<f[n][m]<<endl;
        
    return 0;
}

编辑距离

https://www.acwing.com/problem/content/901/

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int N=14,M=1010;
int n,m;char str[M][N];
int f[N][N];
int comp_str(char a[],char b[]){
    int la=strlen(a+1);int lb=strlen(b+1);
    for(int i=0;i<=la;i++) f[i][0]=i;
    for(int i=0;i<=lb;i++) f[0][i]=i;
    for(int i=1;i<=la;i++)
        for(int j=1;j<=lb;j++)
        {
            f[i][j]=min(f[i-1][j]+1,f[i][j-1]+1);
            if(a[i]==b[j]) f[i][j]=min(f[i][j],f[i-1][j-1]);
            else f[i][j]=min(f[i][j],f[i-1][j-1]+1);
        }
    return f[la][lb];
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++) scanf("%s",str[i]+1);
    while(m--){
        char s[N];int limt;int cnt=0;
        scanf("%s%d",s+1,&limt);
        for(int i=0;i<n;i++){
            if(comp_str(str[i],s)<=limt) cnt++;
        }
        printf("%d\n",cnt);
    }
    
    return 0;
}

 

 

 

posted @ 2024-02-06 11:25  敲代码的6  阅读(18)  评论(0)    收藏  举报