动态规划
背包问题
01背包
二维:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
一维:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
完全背包
二维:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
一维:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
多重背包
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
优化版(二进制):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
分组背包
二维:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
一维:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
线性DP
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
区间DP
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
计数类DP
算法一:完全背包
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
算法二:
状态计算:集合中最小的数为1、集合中最小的数大于1
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
数位统计DP
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
状态压缩DP
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
树形DP
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
记忆化搜索
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }