sdutoj 动态规划专题
作者:互联网
Overview | SDUT OnlineJudge
动态规划:
1.确定dp数组的含义
2.找到递推表达式
3.确定边界值,左边初始化,那一定左退右,上边初始化,一定上推下
动态规划是1生2,2生3的问题,后一个结果一定与前一个或前几个结果有关系
A - 递归的函数
最简单的形式,只是保存了历史记录
1 #include<iostream> 2 using namespace std; 3 int p[21][21][21]={0}; 4 int f(int a,int b,int c) 5 { 6 if(a<=0||b<=0||c<=0) 7 return 1; 8 else if(a>20||b>20||c>20) 9 { 10 if(p[20][20][20]==0) 11 p[20][20][20]=f(20,20,20); 12 return p[20][20][20]; 13 } 14 else if(a<b&&b<c) 15 { 16 if(p[a][b][c]==0) 17 p[a][b][c]=f(a,b,c-1)+f(a,b-1,c-1)-f(a,b-1,c); 18 return p[a][b][c]; 19 } 20 else 21 { 22 if(p[a][b][c]==0) 23 p[a][b][c]=f(a-1,b,c)+f(a-1,b-1,c)+f(a-1,b,c-1)-f(a-1,b-1,c-1); 24 return p[a][b][c]; 25 } 26 } 27 int main() 28 { 29 int a,b,c; 30 while(cin>>a>>b>>c)) 31 cout<<f(a,b,c)<<endl; 32 return 0; 33 }
B - 数字三角形问题(最简单的动态规划)
//动态规划解决问题的思路:
//大化小,把原本的多种情况,每次递减,最后汇总成只有一种情况
//动态规划:1.一定涉及到记录状态
//用一个数组进行记录
// 2.定义出记录数组的含义,比如这道题的含义是最大值
// 3.找到递推关系式,可以把大问题看成两步走的小问题,方便找关系
// 4.找起点并进行初始化,正方向和反方向都想一下
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int n,a[101][101],dp[101][101]; 6 cin>>n; 7 for(int i=1;i<=n;i++) 8 { 9 for(int j=1;j<=i;j++) 10 { 11 cin>>a[i][j]; 12 } 13 } 14 for(int i=1;i<=n;i++) 15 dp[n][i]=a[n][i]; 16 for(int i=n-1;i>=1;i--) 17 { 18 for(int j=1;j<=i;j++) 19 { 20 if(dp[i+1][j]>dp[i+1][j+1]) 21 { 22 dp[i][j]=dp[i+1][j]+a[i][j]; 23 } 24 else 25 dp[i][j]=dp[i+1][j+1]+a[i][j]; 26 } 27 } 28 cout<<dp[1][1]<<endl; 29 return 0; 30 }
C - 小鑫去爬山
//递归公式:未知的位置=已知的位置进行操作
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int n; 6 int a[101][101],dp[101][101]; 7 while(cin>>n) 8 { 9 fill(a[0],a[0]+101*101,0); 10 fill(dp[0],dp[0]+101*101,0); 11 for(int i=1;i<=n;i++) 12 { 13 for(int j=1;j<=i;j++) 14 { 15 cin>>a[i][j]; 16 } 17 } 18 for(int i=1;i<=n;i++) 19 dp[n][i]=a[n][i]; 20 for(int i=n-1;i>=1;i--) 21 { 22 for(int j=1;j<=n;j++) 23 { 24 dp[i][j]=min(dp[i+1][j],dp[i+1][j+1])+a[i][j]; 25 } 26 } 27 cout<<dp[1][1]<<endl; 28 } 29 }
D - 最长公共子序列问题
//初始化了第0行和第0列(左边和上边)
//只能用已经有的求没有的,所以方向只能是左到右或者右到左
//ch1,ch2的下标0,实际上对应的是dp数组的下标1,i,j是dp的下标,i-1,j-1才是ch1,ch2的下标
//也是一个打表的过程,找出每一维的最大值,再更新下一个,有点像01背包
1 #include<bits/stdc++.h> 2 using namespace std; 3 int dp[501][501]; 4 int f(string ch1,string ch2) 5 { 6 int n=ch1.size(); 7 int m=ch2.size(); 8 for(int i=0;i<=n;i++) 9 { 10 dp[i][0]=0; 11 } 12 for(int i=0;i<=m;i++) 13 { 14 dp[0][i]=0; 15 } 16 for(int i=1;i<=n;i++) 17 { 18 for(int j=1;j<=m;j++) 19 { 20 if(ch1[i-1]==ch2[j-1]) 21 { 22 dp[i][j]=dp[i-1][j-1]+1; 23 } 24 else 25 dp[i][j]=max(dp[i-1][j],dp[i][j-1]); 26 } 27 } 28 return dp[n][m]; 29 } 30 int main() 31 { 32 string ch1,ch2; 33 cin>>ch1>>ch2; 34 cout<<f(ch1,ch2)<<endl; 35 return 0; 36 }
E - 最长上升子序列
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[1010]; 4 int dp[1010]; 5 int main() 6 { 7 int n; 8 int mx=0; 9 cin>>n; 10 for(int i=1;i<=n;i++) 11 { 12 cin>>a[i]; 13 } 14 for(int i=1;i<=n;i++) 15 { 16 dp[i]=1; 17 for(int j=1;j<=i;j++) 18 { 19 if(a[i]>a[j]) 20 dp[i]=max(dp[i],dp[j]+1); 21 } 22 mx=max(dp[i],mx); 23 } 24 cout<<mx<<endl; 25 return 0; 26 }
F - 上升子序列
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int maxn=0; 6 int n; 7 int a[1010],dp[1010]; 8 cin>>n; 9 for(int i=1;i<=n;i++) 10 { 11 cin>>a[i]; 12 } 13 for(int i=1;i<=n;i++) 14 { 15 dp[i]=a[i]; 16 for(int j=1;j<=i;j++) 17 { 18 if(a[i]>a[j]) 19 { 20 dp[i]=max(dp[i],dp[j]+a[i]); 21 } 22 } 23 maxn=max(dp[i],maxn); 24 } 25 cout<<maxn<<endl; 26 return 0; 27 }
H - 取数字问题
#include<bits/stdc++.h> using namespace std; int a[100][100]; int dp[100][100]; int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cin>>a[i][j]; } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { dp[i][j]=min(dp[i-1][j],dp[i][j-1])+a[i][j]; } } if(dp[n][m]<=0) cout<<"-1"<<endl; else cout<<dp[n][m]<<endl; return 0; }
I - 免费馅饼
//输入两个数据,大概率是二维
//后推前
//第一秒!=第零秒 ,注意边界!!!
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[100001][12]; 4 int main() 5 { 6 ios::sync_with_stdio(false); 7 cin.tie(0); 8 cout.tie(0); 9 int n; 10 int x,t; 11 while(cin>>n,n) 12 { 13 int rant=0; 14 fill(a[0],a[0]+100001*12,0); 15 for(int i=0;i<n;i++) 16 { 17 cin>>x>>t; 18 a[t][x]++; 19 if(rant<t) 20 { 21 rant=t; 22 } 23 } 24 for(int i=rant-1;i>=0;i--) 25 { 26 for(int j=0;j<=10;j++) 27 { 28 if(j==0) 29 { 30 a[i][j]+=max(a[i+1][j],a[i+1][j+1]); 31 } 32 else 33 { 34 a[i][j]+=max(max(a[i+1][j-1],a[i+1][j]),a[i+1][j+1]); 35 } 36 } 37 } 38 cout<<a[0][5]<<endl; 39 } 40 return 0; 41 }
J - 走迷宫(dfs)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,b1,b2,e1,e2; 4 int dit[4][2]={0,-1,-1,0,0,1,1,0}; 5 int a[30][30],b[100]; 6 int book[30][30]; 7 int flag=0; 8 int ii=1; 9 void dfs(int b1,int b2,int ii) 10 { 11 if(b1==e1&&b2==e2) 12 { 13 flag=1; 14 for(int i=1;i<=ii-2;i+=2) 15 { 16 cout<<"("<<b[i]<<","<<b[i+1]<<")"; 17 if(i!=ii-2) 18 cout<<"->"; 19 } 20 cout<<endl; 21 return; 22 } 23 for(int i=0;i<4;i++) 24 { 25 int x=b1+dit[i][0]; 26 int y=b2+dit[i][1]; 27 if(a[x][y]==0||book[x][y]==1) 28 continue; 29 book[x][y]=1; 30 b[ii]=x; 31 b[ii+1]=y; 32 dfs(x,y,ii+2); 33 book[x][y]=0; 34 } 35 } 36 int main() 37 { 38 while(scanf("%d %d",&n,&m) == 2) 39 { 40 for(int i=1;i<=n;i++) 41 { 42 for(int j=1;j<=m;j++) 43 { 44 cin>>a[i][j]; 45 } 46 } 47 cin>>b1>>b2>>e1>>e2; 48 book[b1][b2]=1; 49 b[1]=b1; 50 b[2]=b2; 51 ii+=2; 52 dfs(b1,b1,ii); 53 if(!flag) 54 cout<<"-1"<<endl; 55 } 56 57 return 0; 58 }
标签:std,专题,20,sdutoj,int,include,101,动态,dp 来源: https://www.cnblogs.com/inawaken/p/16278576.html