DP入门题--数塔问题(poj1163)
2015-11-30 18:07
344 查看
做了10来道DP题再做这个数塔问题明显上手,不仅写的快,一次AC,还用了两种方法。由此看来深入浅出不是没有道理啊,哈哈~~
数塔问题的状态转移方程很容易得到,我是从上往下想的(即递推的思想),这里说一下经常看到的两种DP的写法,一种是用递推的方式,它的要求是每一次求的这个状态,它计算肯定是由前面已经算出来的状态得到的,比较容易实现,但是不是每一道题都那么容易想出,另一种是记忆化搜索的方式, 即我算出一个结果就保存,以便后来使用(比如什么初始化数组为负,算出结果就保存,一旦发现数组为正说明计算过了,直接使用)。
这里我都是用的递推的方式,只不过第二种方式取了个巧,因为我是从1~n而dp[i-1][j-1]的j-1是可能到0的,但是dp[i-1][0]肯定是没有dp[i-1][1]大的(dp[i-1][0]初始化为0,memset)
数塔问题的状态转移方程很容易得到,我是从上往下想的(即递推的思想),这里说一下经常看到的两种DP的写法,一种是用递推的方式,它的要求是每一次求的这个状态,它计算肯定是由前面已经算出来的状态得到的,比较容易实现,但是不是每一道题都那么容易想出,另一种是记忆化搜索的方式, 即我算出一个结果就保存,以便后来使用(比如什么初始化数组为负,算出结果就保存,一旦发现数组为正说明计算过了,直接使用)。
这里我都是用的递推的方式,只不过第二种方式取了个巧,因为我是从1~n而dp[i-1][j-1]的j-1是可能到0的,但是dp[i-1][0]肯定是没有dp[i-1][1]大的(dp[i-1][0]初始化为0,memset)
#include <stdio.h> #include <string.h> int max(int a,int b) { return a>b?a:b; } int main() { int i,j,n,ans; int a[105][105]; int dp[105][105]; memset(a,0,sizeof(a)); scanf("%d",&n); for (i=1;i<=n;i++) for (j=1;j<=i;j++) { scanf("%d",&a[i][j]); } dp[1][1]=a[1][1]; for (i=2;i<=n;i++) for (j=1;j<=n;j++) { if (j==1)//每一行的第一个直接从上一行的第一个加上这一行的第一个得到得到 dp[i][j]=dp[i-1][j]+a[i][j]; else if (j==i)//每一行的最后一个直接从上一行的末尾加上这一行的最后一个得到 dp[i][j]=dp[i-1][j-1]+a[i][j]; else dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+a[i][j]; } ans=-99999; for (i=1;i<=n;i++) ans=max(ans,dp [i]);//在最后一行找出较大的那个数 printf("%d\n",ans); return 0; }
#include <stdio.h> #include <string.h> int max(int a,int b) { return a>b?a:b; } int main() { int i,j,n,ans; int a[105][105]; int dp[105][105]; memset(a,0,sizeof(a)); memset(dp,0,sizeof(dp)); scanf("%d",&n); for (i=1;i<=n;i++) for (j=1;j<=i;j++) scanf("%d",&a[i][j]); for (i=1;i<=n;i++) for (j=1;j<=n;j++) dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+a[i][j]; ans=-9999; for(i=1;i<=n;i++) ans=max(ans,dp [i]); printf("%d\n",ans); return 0; }变种题:LightOJ 1004
#include <stdio.h> #include <string.h> __int64 max(__int64 a,__int64 b) { return a>b?a:b; } __int64 s[300][300]; __int64 dp[300][300]; int main() { int T; int n,m,i,j,num; scanf("%d",&T); num=1; while(T--) { memset(s,0,sizeof(s)); memset(dp,0,sizeof(dp)); scanf("%d",&n); for (i=1;i<=n;i++) for (j=1;j<=i;j++) scanf("%d",&s[i][j]); for (i=n+1;i<=2*n-1;i++) for (j=1;j<=2*n-i;j++) scanf("%d",&s[i][j]); for (i=1;i<=n;i++) for (j=1;j<=i;j++) dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+s[i][j]; for (i=n+1;i<=n*2-1;i++) for (j=1;j<=2*n-i;j++) dp[i][j]=max(dp[i-1][j],dp[i-1][j+1])+s[i][j]; printf("Case %d: %d\n",num,dp[2*n-1][1]); num++; } return 0; }
相关文章推荐
- [转载]Python注册表信息丢失的解决方案
- org.hibernate.MappingException: Unknown entity常见问题(新手需注意)
- delphi idHttp下载文件
- androidd时光轴效果实现
- 面向对象编程(上)
- JqGrid使用经验
- js特效之最近的两个星期天
- 第十四周“知原理”题目4
- 310 Minimum Height Trees(Medium)
- MYSQL的常用命令和增删改查语句和数据类型
- Linux下Rsync+sersync实现数据实时同步
- nginx 301 永久重定向
- 判断字符串是否包含某些字符
- windows下apache+php+mysql 环境配置方法
- poj 2184 Cow Exhibition 01背包
- iOS滤镜效果的实现:CoreImage
- Flex布局理论小结
- java获取最新地区
- 进化计算简介和遗传算法的实现--AForge.NET框架的使用(六)
- mysql常用基本操作