经典dp模型的变形(未完待续。。)
来源:互联网 发布:域名推广 编辑:程序博客网 时间:2024/04/30 00:24
这几天做了几道dp题,发现有几道是很经典的dp模型的变形,总结一下:
数字三角形
这算是dp的最最最入门的题了吧,但是这题变形的话,还是需要好好想想才能看出来的。
题目:hdu 1176 免费馅饼
题意:
一定时间,天上会从某个位置Xi掉下一块馅饼,1< =xi< =10,这个人位于xi,只能接到xi-1,xi,xi+1,三处之一,问这人可以接到的最多馅饼?
分析:
这题想想还是挺有意思的QAQ,因为是按照时间落馅饼,所以dp的方向是显然的,就是按照时间,第二维当然就是位置了!所以用dp[i][j]表示在i时刻这个人在j位置可以得到的最大馅饼数,num[i][j]表示i时刻j位置落下的馅饼数,不难写出dp方程:
dp[i][x]=max(dp[i-1][x-1],dp[i-1][x],dp[i-1][x+1])+num[i][x]
想明白后,0时刻在5这个位置,然后顺着时间转移,转移到最后一块馅饼落下的时刻,那么这题不就做出来了吗?当然可以!注意下边界即可。
仔细想想这题,这不就是数字三角形吗?所以逆推很容易就可以搞定了!
const int N=1e5+2;int n,x,T,t,f[N][11];int main(){ while(~scanf("%d",&n)&&n){ T=0; memset(f,0,sizeof(f)); for(int i=0;i<n;i++){ scanf("%d%d",&x,&t); f[t][x]++; if(T<t)T=t; } for(int i=T-1;i>=0;i--){ for(int j=1;j<=9;j++) f[i][j]+=max(f[i+1][j+1],max(f[i+1][j],f[i+1][j-1])); f[i][0]+=max(f[i+1][0],f[i+1][1]); f[i][10]+=max(f[i+1][10],f[i+1][9]); } cout<<f[0][5]<<endl; } return 0;}
背包问题
背包问题无疑是变形最多的一类dp题,要想掌握好这类题目,关键还是要深刻理解01背包和完全背包!当然还有更多变形,像分组背包,有依赖的背包,泛化背包等,都是些不好掌握的东东,当然做题时如果能看出这是背包的题目,就离解决问题更近了一大
步!
(此处应有各种背包的分类,等多做几道题后再补QAQ)
完全背包
题目:hdu 1114 Piggy-Bank
题意:
存钱罐里有一些硬币,总共重量是F,空罐重量是E,给出n种钱币,每种钱币的有两个参数,v价值,w重量。问存钱罐中最少的价值是多少?
分析:
赤裸裸的完全背包的题目,注意初始化。
const int INF=0x3f3f3f3f;const int N=1e4+9;int n;int E,F;int f[N],p[N],w[N];int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%d",&E,&F); F-=E; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&p[i],&w[i]); } for(int i=1;i<=F;i++)f[i]=INF; f[0]=0; for(int i=1;i<=n;i++){ for(int v=w[i];v<=F;v++) f[v]=min(f[v],f[v-w[i]]+p[i]); } if(f[F] == INF) printf("This is impossible.\n"); else printf("The minimum amount of money in the piggy-bank is %d.\n",f[F]); } return 0;}
最长上升子序列 LIS
最长上升子序列变形是比较多的,可以先看我以前写的这篇:http://blog.csdn.net/hjt_fathomless/article/details/52176146
题目的话,有很多,比如矩形嵌套(按一边排序后,就可以LIS了),叠木块等!
题目:http://blog.csdn.net/hjt_fathomless/article/details/52176513
最长公共子序列 LCS
可以求解最长回文子序列LPS(Longest Palindromic Subsequence)问题
题目:http://blog.csdn.net/hjt_fathomless/article/details/52424136
简单的dp题
简单的dp题是什么东西?就是决策是显然的,一般递推就可以解决,这种题决策都不会太复杂(反正复杂的我也不会做QAQ),而且方向是明显的,所以是简单的。
比如走楼梯那种题,只有两个决策,一步or两步,方向是从0—n(楼底到楼上)。再比如上边所述的数字三角形,决策和方向都是很容易看出来的(所以才是入门题啊)。碰见这种题,那就偷着乐吧!
题目:hdu 1260 Tricks
题意:
售票员有两种选择,一次一票or两票,问花时最少?
分析:
这题是不是很简单,决策是显然的,一票or两票,方向从第一个人到最后一个人楼,这不是跟走楼梯那题一样吗?所以是简单dp!
const int N=1e5+2;int a[N],b[N],f[N],t[5];char c[5];int main(){ int n; int T;scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=2;i<=n;i++)scanf("%d",&b[i]); f[1]=a[1]; for(int i=2;i<=n;i++) f[i]=min(f[i-1]+a[i],f[i-2]+b[i]); t[1]=f[n]/3600; f[n]%=3600; t[2]=f[n]/60; f[n]%=60; t[3]=f[n]; t[1]+=8; c[1]='a'; c[2]='m'; if(t[1]>12){ t[1]-=12; c[1]='p'; } printf("%02d:%02d:%02d %c%c\n",t[1],t[2],t[3],c[1],c[2]); } return 0;}
- 经典dp模型的变形(未完待续。。)
- DP总结..未完待续
- hdu2476【区间DP,未完待续】
- la_4727Jump ( 经典模型变形 )
- 未完待续的几个命令
- java学习必看的经典文章汇总(未完待续)
- 未完待续
- 未完待续
- 未完待续
- 未完,待续
- 未完待续~~~~~~~~~~~~~~~~
- 未完待续
- 未完待续
- 未完待续
- 未完待续
- 未完待续
- 用C++实现《经典c程序100例》(未完待续)
- Android经典面试题总结(未完待续)
- Android中需要记住的几个问题
- 按住放大,带音效的自定义按钮ZoomImageView
- pandas wind 数据提取简单demo
- 关于编译gdk
- Common Subsequence(lcs)
- 经典dp模型的变形(未完待续。。)
- iOS Core Bluetooth 蓝牙
- HP-UX执行脚本报错The specified value exceeds the user's allowable limit;Cannot create the specifie file
- COGS锯木厂选址(斜率优化)
- 售货员难题 状压dp
- 事件的三个阶段
- arcengine打开cad文件的几种方法
- Java 如何查询硬盘所有文件
- cordova 文件上传