1.数字三角形
学习链接:http://blog.csdn.net/zwhlxl/article/details/46225947
输入样例:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出样例:
30
递归代码:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 101 #define MAX 1<<30 #define V vector<int> using namespace std; int num[LEN][LEN]; int dp[LEN][LEN]; int n; int getMax(int i,int j){ if(dp[i][j]>=0) return dp[i][j]; if(i==n) return num[i][j]; int a=getMax(i+1,j); int b=getMax(i+1,j+1); dp[i][j]=max(a,b)+num[i][j]; return dp[i][j]; } int main(){ freopen("数字三角形.txt","r",stdin); int i,j; scanf("%d",&n); for(i=1;i<=n;i++){ for(j=1;j<=i;j++){ I("%d",&num[i][j]); } } for(i=1;i<=n;i++) fill(dp[i],dp[i]+1+n,-1); printf("%d",getMax(1,1)); return 0; }
循环代码:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 101 #define MAX 1<<30 #define V vector<int> using namespace std; int num[LEN][LEN]; int dp[LEN][LEN]; int n; int main(){ freopen("数字三角形.txt","r",stdin); int i,j; scanf("%d",&n); for(i=1;i<=n;i++){ for(j=1;j<=i;j++){ I("%d",&num[i][j]); } } for(i=1;i<=n;i++) dp[n][i]=num[n][i]; for(i=n-1;i>=1;i--){ for(j=1;j<=i;j++){ dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+num[i][j]; } } printf("%d",dp[1][1]); return 0; }
2.滑雪
测试数据演示:
(测试数据呈螺旋形滑下)
代码:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 200 #define MAX 1<<30 #define V vector<int> using namespace std; int n,m; int dp[LEN][LEN],a[LEN][LEN]; int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1}; void init(){ int i,j; FF(i,n)FF(j,m){ dp[i][j]=-1; } } int dfs(int x,int y){ if(dp[x][y]!=-1) //已经记录过了 return dp[x][y]; dp[x][y]=1; int k; FF(k,4){//构造四个方向 int tx=x+dx[k],ty=y+dy[k]; if(tx>=0 && tx<n && ty>=0 && ty<m && a[x][y]>a[tx][ty] ){ dp[x][y]=max(dp[x][y],dfs(tx,ty)+1); } } return dp[x][y]; } int main(){ // freopen("滑雪.txt","r",stdin); int i,j,N; I("%d",&N); while(N--){ I("%d %d",&n,&m); FF(i,n)FF(j,m){ I("%d",&a[i][j]); } int ans=0; F(i,0,n) F(j,0,m){ init(); ans=max(ans,dfs(i,j)); } O("%d ",ans); } return 0; }
(感觉代码还不够优化,待调优)
3.吃吃吃
测试数据演示:
(注意到只能从图中中间3个区域出发,题目疯狂卡我语文)
代码:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 1000 #define MAX 1<<30 #define V vector<int> using namespace std; int dp[LEN][LEN]; int a[LEN][LEN]; int n,m; int dfs(int x,int y){ if(dp[x][y]>-MAX){ return dp[x][y]; } if(x==1 ){//|| y==1 || y==m return a[x][y]; } int dy[3]={-1,0,1}; int i,j; for(i=0;i<3;i++){ int ty=y+dy[i]; if(ty>=1 && ty<=m){ dp[x][y]=max(dp[x][y],dfs(x-1,ty)+a[x][y]); } } return dp[x][y]; } int main(){ // freopen("吃吃吃.txt","r",stdin); int i,j; scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ I("%d",&a[i][j]); } } int ans=0; for(j=0;j<3;j++){ //initialize for(i=1;i<=n;i++) fill(dp[i],dp[i]+1+m,-MAX); ans=max(ans,dfs(n,m/2+j)); } printf("%d",ans); return 0; }
4.传纸条
测试数据演示:
根据传统算法设计的DP矩阵:,与正确答案相悖。
DP矩阵分析图:
对角线一直从3=1+2(序号2)循环到10=n+m-1(序号length-1)
理解:红块表示纸条1,蓝块表示纸条2,纸条1有i-1和i两个前驱,纸条2有j-1和j两个前驱。四个情况叠加有四种可能,对四种情况进行遍历取最大值
代码:
#include <stdio.h> #include <memory.h> #include <math.h> #include <cstring> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map> #define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 101 #define MAX 1<<30 #define V vector<int> using namespace std; int dp[LEN*2][LEN][LEN]; //[对角线编号][纸条1纵坐标][纸条2纵坐标] int a[LEN][LEN]; int main(){ // freopen("D:/CbWorkspace/动态规划/传纸条.txt","r",stdin); int n,m,i,j,k; I("%d %d",&n,&m); F(i,1,n+1) F(j,1,m+1) I("%d",&a[i][j]); //首先对dp矩阵进行初始化 memset(dp,-1,sizeof(dp)); dp[2][1][1]=0; //顶点为0 for(k=3;k<n+m;k++){ //对角线 for(i=1;i<m;i++){ //纸条1 纵坐标 for(j=i+1;j<=m;j++){ //纸条2 纵坐标(总是在纸条1右边) //四种组合 dp[k][i][j]=max(dp[k][i][j],dp[k-1][i][j]); dp[k][i][j]=max(dp[k][i][j],dp[k-1][i-1][j]); dp[k][i][j]=max(dp[k][i][j],dp[k-1][i][j-1]); dp[k][i][j]=max(dp[k][i][j],dp[k-1][i-1][j-1]); dp[k][i][j]+=a[k-i][i]; //纸条 1 的value dp[k][i][j]+=a[k-j][j]; //纸条 2 的value } } } O("%d",dp[n+m-1][m-1][m]); return 0; }