动态规划

背包问题

01背包

AcWing 2. 01背包问题

二维:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e3+5;
int n,m,v[N],w[N],f[N][N];
int main()
{
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i)cin>>v[i]>>w[i];
    for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j){
            if(j<v[i])f[i][j]=f[i-1][j];
            else
                f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);
        }
    }
    cout<<f[n][m];
    return 0;
}
View Code

一维:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e3+5;
int n,m,v[N],w[N],f[N];
int main()
{
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i)cin>>v[i]>>w[i];
    for(int i=1;i<=n;++i){
        for(int j=m;j>=v[i];--j){
                f[j]=max(f[j],f[j-v[i]]+w[i]);
        }
    }
    cout<<f[m];
    return 0;
}
View Code

 

完全背包

AcWing 3. 完全背包问题

二维:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e3+5;
int n,m,v[N],w[N],f[N][N];
int main()
{
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i)cin>>v[i]>>w[i];
    for(int i=1;i<=n;++i){
        for(int j=0;j<=m;++j){
            if(j<v[i])f[i][j]=f[i-1][j];
            else f[i][j]=max(f[i-1][j],f[i][j-v[i]]+w[i]);
        }
    }
    cout<<f[n][m];
    return 0;
}
View Code

一维:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e3+5;
int n,m,v[N],w[N],f[N];
int main()
{
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i)cin>>v[i]>>w[i];
    for(int i=1;i<=n;++i){
        for(int j=v[i];j<=m;++j){
            f[j]=max(f[j],f[j-v[i]]+w[i]);
        }
    }
    cout<<f[m];
    return 0;
}
View Code

 

多重背包

AcWing 4. 多重背包问题

 

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e2+5;
int n,m,v[N],w[N],f[N][N],s[N];
int main()
{
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        cin>>v[i]>>w[i]>>s[i];
    }
    for(int i=1;i<=n;++i){
        for(int j=0;j<=m;++j){
            for(int k=0;k<=s[i]&&k*v[i]<=j;++k){
                f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
            }
        }
    }
    cout<<f[n][m];
    return 0;
}
View Code

优化版(二进制):

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=12010;
int n,m,v[N],w[N],f[N],s[N],cnt;
int main()
{
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        int a,b,s;
        cin>>a>>b>>s;
        int k=1;
        while(k<=s){
            cnt++;
            v[cnt]=a*k;
            w[cnt]=b*k;
            s-=k;
            k*=2;
        }
        if(s>0){
            cnt++;
            v[cnt]=a*s;
            w[cnt]=b*s;
        }
    }
    n=cnt;
    for(int i=1;i<=n;++i)
        for(int j=m;j>=v[i];--j)
            f[j]=max(f[j],f[j-v[i]]+w[i]);
    cout<<f[m];
    return 0;
}
View Code

 

 

分组背包

AcWing 9. 分组背包问题

 

二维:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=12010;
int n,m,v[105][105],w[105][105],f[105][105],s[105];
int main()
{
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        cin>>s[i];
        for(int j=1;j<=s[i];++j)cin>>v[i][j]>>w[i][j];
    }
    for(int i=1;i<=n;++i){
        for(int j=m;j>=0;--j){
            f[i][j]=f[i-1][j];
            for(int k=1;k<=s[i];++k){
                if(v[i][k]<=j)f[i][j]=max(f[i][j],f[i-1][j-v[i][k]]+w[i][k]);
            }
        }
    }
    cout<<f[n][m];
    return 0;
}
View Code

 

一维:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=12010;
int n,m,v[105][105],w[105][105],f[N],s[105];
int main()
{
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i){
        cin>>s[i];
        for(int j=1;j<=s[i];++j)cin>>v[i][j]>>w[i][j];
    }
    for(int i=1;i<=n;++i){
        for(int j=m;j>=0;--j){
            for(int k=1;k<=s[i];++k){
                if(v[i][k]<=j)f[j]=max(f[j],f[j-v[i][k]]+w[i][k]);
            }
        }
    }
    cout<<f[m];
    return 0;
}
View Code

 

 

线性DP

AcWing 898. 数字三角形

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=5e2+5,INF=1e9;

int a[N][N],f[N][N],n;
int main()
{
    cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=i;++j)cin>>a[i][j];
    for(int i=0;i<=n;++i)
        for(int j=0;j<=n+1;++j)f[i][j]=-INF;
    f[1][1]=a[1][1];
    for(int i=2;i<=n;++i)
        for(int j=1;j<=i;++j)
            f[i][j]=max(f[i-1][j],f[i-1][j-1])+a[i][j];
    int ans=-INF;
    for(int i=1;i<=n;++i)ans=max(ans,f[n][i]);
    cout<<ans;
    return 0;
}
View Code

AcWing 895. 最长上升子序列

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e3+5,INF=1e9;


int f[N],a[N],n;
int main(){
    cin>>n;
    for(int i=1;i<=n;++i)cin>>a[i];
    for(int i=1;i<=n;++i){
        f[i]=1;
        for(int j=1;j<i;++j){
            if(a[j]<a[i])
                f[i]=max(f[i],f[j]+1);
        }
    }
    int ans=0;
    for(int i=1;i<=n;++i)ans=max(ans,f[i]);
    cout<<ans;
    return 0;
}
View Code

AcWing 896. 最长上升子序列 II

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e5+5,INF=1e9;
int n,a[N];
int main(){
    cin>>n;
    for(int i=0;i<n;++i)cin>>a[i];
    vector<int>q;
    q.push_back(a[0]);
    for(int i=1;i<n;++i){
        if(a[i]>q.back())q.push_back(a[i]);
        else *lower_bound(q.begin(),q.end(),a[i])=a[i];
    }
    cout<<q.size();
    return 0;
}
View Code

 

AcWing 902. 最短编辑距离

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e3+5,INF=1e9;
int n,m,f[N][N];
char a[N],b[N];
int main(){
    cin>>n>>a+1>>m>>b+1;
    memset(f,0x3f,sizeof f);
    for(int i=1;i<=n;++i)f[i][0]=i;
    for(int i=1;i<=m;++i)f[0][i]=i;
    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]+1);
            else f[i][j]=min(f[i][j],f[i-1][j-1]);
        }
    cout<<f[n][m];
    return 0;
}
View Code

 

AcWing 899. 编辑距离

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=15,INF=1e9,M=1e3+10;
int n,m,k;
char a[M][N];
int f[N][N];
int P(char a[],char b[]){
    int la=strlen(a+1),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],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(){
    cin>>n>>m;
    for(int i=0;i<n;++i)cin>>(a[i]+1);
    while(m--){
        char b[N];
        cin>>(b+1)>>k;
        int res=0;
        for(int i=0;i<n;++i)
            if(P(a[i],b)<=k)res++;
        cout<<res<<'\n';
    }
    return 0;
}
View Code

 

AcWing 897. 最长公共子序列

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e3+5,INF=1e9;
int f[N][N],n,m;
char a[N],b[N];
int main(){
    cin>>n>>m;
    cin>>a+1>>b+1;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j){
            if(a[i]==b[j])
                f[i][j]=max(f[i][j],f[i-1][j-1]+1);
            else f[i][j]=max(f[i-1][j],f[i][j-1]);
        }
    cout<<f[n][m];
    return 0;
}
View Code

 

区间DP

AcWing 282. 石子合并

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=3e2+5,INF=1e9;




int f[N][N],n,s[N];
int main(){
    cin>>n;
    for(int i=1;i<=n;++i){
        cin>>s[i];s[i]+=s[i-1];
    }
    memset(f,0x3f,sizeof f);
    for(int len=1;len<=n;++len){
        for(int i=1;i+len-1<=n;++i){
            int r=i+len-1;
            if(len==1){f[i][r]=0;continue;}
            for(int k=i;k<r;++k)
                f[i][r]=min(f[i][r],f[i][k]+f[k+1][r]+s[r]-s[i-1]);
        }
    }
    cout<<f[1][n];
    return 0;
}
View Code

 

计数类DP

AcWing 900. 整数划分

算法一:完全背包

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e3+5,INF=1e9,M=1e9+7;
ll n,f[N];
int main(){
    cin>>n;
    f[0]=1;
    for(int i=1;i<=n;++i)
        for(int j=i;j<=n;++j)
            f[j]=(f[j]+f[j-i])%M;
    cout<<f[n];
    return 0;
}
View Code

算法二:

状态计算:集合中最小的数为1、集合中最小的数大于1

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e3+5,INF=1e9,M=1e9+7;
ll n,f[N][N];
int main(){
    cin>>n;
    f[0][0]=1;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=i;++j)
            f[i][j]=(f[i-1][j-1]+f[i-j][j])%M;
    ll ans=0;
    for(int i=1;i<=n;++i)ans=(ans+f[n][i])%M;
    cout<<ans;
    return 0;
}
View Code

数位统计DP

AcWing 338. 计数问题

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1e5+5,INF=1e9,M=1e3+10;
int a,b;
int get(vector<int>s,int l,int r){
    int res=0;
    for(int i=l;i>=r;--i)
        res=res*10+s[i];
    return res;
}
int P(int x){
    int res=1;
    while(x--)res*=10;
    return res;
}
int count(int n,int x){
    if(n==0)return 0;
    vector<int>sum;
    while(n){
        sum.push_back(n%10);
        n/=10;
    }
    int s=sum.size(),res=0;
    for(int i=s-1-!x;i>=0;--i){
        if(i<s-1){
            res+=get(sum,s-1,i+1)*P(i);
            if(!x)res-=P(i);
        }
        if(sum[i]==x)res+=(get(sum,i-1,0)+1);
        else if(sum[i]>x)res+=P(i);
    }
    return res;
}
int main(){
    while(cin>>a>>b,a||b){
        if(a>b)swap(a,b);
        for(int i=0;i<=9;++i)
            cout<<count(b,i)-count(a-1,i)<<' ';
        cout<<'\n';
    }
    return 0;
}
View Code

 

状态压缩DP

AcWing 291. 蒙德里安的梦想

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1<<12,INF=1e9,M=1e3+10;
ll n,m,f[12][N];
bool st[N];
int main(){
    while(cin>>n>>m,n||m){
        for(int i=0;i<1<<n;++i){
            int cnt=0;
            st[i]=true;
            for(int j=0;j<n;++j){
                if(i>>j&1){
                    if(cnt&1)st[i]=false;
                    cnt=0;
                }
                else cnt++;
            }
            if(cnt&1)st[i]=false;
        }
        memset(f,0,sizeof f);
        f[0][0]=1;
        for(int i=1;i<=m;++i)
            for(int j=0;j<1<<n;++j)
                for(int k=0;k<1<<n;++k)
                    if((j&k)==0&&st[k|j])
                        f[i][j]+=f[i-1][k];
        cout<<f[m][0]<<'\n';
    }
    return 0;
}
View Code

 

AcWing 91. 最短Hamilton路径

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=1<<12,INF=1e9,M=1e3+10;
int n,w[20][20],f[1<<20][20];
int main(){
    cin>>n;
    for(int i=0;i<n;++i)
        for(int j=0;j<n;++j)cin>>w[i][j];
    memset(f,0x3f,sizeof f);
    f[1][0]=0;
    for(int i=0;i<1<<n;++i)
        for(int j=0;j<n;++j)
            if(i>>j&1){
                for(int k=0;k<n;++k)
                    if(i>>k&1){
                        f[i][j]=min(f[i][j],f[i-(1<<j)][k]+w[k][j]);
                    }
            }
    cout<<f[(1<<n)-1][n-1];
    return 0;
}
View Code

 

树形DP

AcWing 285. 没有上司的舞会

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=6e3+5,INF=1e9,M=1e3+10;
int n,ha[N],f[N][2],e[N],ne[N],h[N],idx;
bool st[N];
void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u){
    f[u][1]=ha[u];
    for(int i=h[u];i!=-1;i=ne[i]){
        int j=e[i];
        dfs(j);
        f[u][1]+=f[j][0];
        f[u][0]+=max(f[j][0],f[j][1]);
    }
}
int main(){
    cin>>n;
    memset(h,-1,sizeof h);
    for(int i=1;i<=n;++i)cin>>ha[i];
    int a,b;
    for(int i=2;i<=n;++i){
        cin>>a>>b;
        st[a]=true;
        add(b,a);
    }
    int t=1;
    while(st[t]){t++;}
    dfs(t);
    cout<<max(f[t][0],f[t][1]);
    return 0;
}
View Code

 

记忆化搜索


AcWing 901. 滑雪

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N=300+5,INF=1e9,M=1e3+10;
int n,m,a[N][N],d[N][N];
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
int dp(int x,int y){
    int &v=d[x][y];
    if(v!=-1)return v;
    v=1;
    for(int i=0;i<4;++i){
        int xx=x+dx[i],yy=y+dy[i];
        if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&a[xx][yy]<a[x][y]){
            v=max(v,dp(xx,yy)+1);
        }
    }
    return v;
}
int main(){
    cin>>n>>m;
    memset(d,-1,sizeof d);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)cin>>a[i][j];
    int res=0;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j){
            res=max(res,dp(i,j));
        }
    cout<<res;
    return 0;
}
View Code

 

posted @ 2023-02-06 23:07  bible_w  阅读(11)  评论(0编辑  收藏  举报