本文中的习题来自 Loi_DQS dalao整理的DP学习资料
1.【codevs1220】数字三角形问题
记忆化搜索:
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int sz=1000+50; 5 int map[sz][sz],dp[sz][sz]; 6 int n; 7 int dfs(int i,int j) 8 { 9 if(i==n) return map[i][j]; 10 if(dp[i+1][j]==0) dp[i+1][j]=dfs(i+1,j); 11 if(dp[i+1][j+1]==0) dp[i+1][j+1]=dfs(i+1,j+1); 12 return dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+map[i][j]; 13 } 14 int main() 15 { 16 scanf("%d",&n); 17 for(int i=1;i<=n;i++) 18 for(int j=1;j<=i;j++) 19 scanf("%d",&map[i][j]); 20 printf("%d",dfs(1,1)); 21 return 0; 22 }
顺推:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int sz=1000+50; 6 int map[sz][sz],dp[sz][sz]; 7 int main() 8 { 9 int n; 10 scanf("%d",&n); 11 for(int i=1;i<=n;i++) 12 for(int j=1;j<=i;j++) 13 scanf("%d",&map[i][j]); 14 for(int i=1;i<=n;i++) 15 for(int j=1;j<=i;j++) 16 dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+map[i][j]; 17 int ans=-999; 18 for(int i=1;i<=n;i++) 19 ans=max(ans,dp[n][i]); 20 printf("%d",ans); 21 return 0; 22 }
逆推:
#include<cstdio> #include<algorithm> using namespace std; const int sz=1000+50; int map[sz][sz],dp[sz][sz]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) scanf("%d",&map[i][j]); for(int i=n;i>=0;i--) for(int j=1;j<=i;j++) dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+map[i][j]; printf("%d",dp[1][1]); return 0; }
2.【codevs1576】最长上升子序列(LIS)问题
常规做法
#include<cstdio> #include<algorithm> using namespace std; const int sz=5000+50; int num[sz],dp[sz]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&num[i]); int ans=0; for(int i=1;i<=n;i++) { dp[i]=1;//初始化 以i结尾的LIS长度最小为1 for(int j=1;j<i;j++) if(num[j]<num[i]) dp[i]=max(dp[i],dp[j]+1); ans=max(ans,dp[i]); } printf("%d",ans); return 0; }
O(nlogn)做法。。。
3.方格取数问题
#include<cstdio> #include<algorithm> using namespace std; const int sz=5000+50; int map[sz][sz],dp[sz][sz]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&map[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { dp[i][j]=max(dp[i-1][j],dp[i][j-1])+map[i][j]; } printf("%d",dp[n][m]); return 0; }
4.【codevs1102】01背包问题
滚动数组
#include<cstdio> #include<algorithm> using namespace std; const int sz=1000+10; struct node{ int tim,val; }th[sz]; int dp[sz]; int main() { int t,m; scanf("%d%d",&t,&m); for(int i=1;i<=m;i++) { int tim,val; scanf("%d%d",&tim,&val); th[i].tim=tim,th[i].val=val; } for(int i=1;i<=m;i++) for(int j=t;j>=th[i].tim;j--) { dp[j]=max(dp[j],dp[j-th[i].tim]+th[i].val); } printf("%d",dp[t]); return 0; }