hdu4283
2014-03-01 11:58
330 查看
区间dp。。。好难的说
这题目咋一看根本想不到是区间dp,我是做区间dp专题时看到的这题,但是就算知道是用区间dp做也划分不好状态,后来瞄了一眼状态划分,顿时被这题的思路惊呆了,将栈的特性应用的淋漓尽致,让人叹服。
题目分析:和普通的区间dp不同,这题无论任何情况下,都设当前区间最前面的一个元素为分割点,应用了栈的特性:若第一个元素第k个出栈,则第二到k个元素肯定在第一个元素之前出栈,第k+1到最后一个元素肯定在第k个之后出栈,这样便把区间划分成了两段,以此状态依次划分,加上记忆化搜索,便能得出答案。这题的记忆化搜索也和一般区间dp不同,区间内的值会随着区间之前共取出多少元素的改变而改变,故对要记忆的区间,记录下共有多少元素在此区间之前出栈,然后下次用到该区间是和记录的出栈元素个数比较,去掉多加或多减的部分,便能完成记忆化搜索。
这题目咋一看根本想不到是区间dp,我是做区间dp专题时看到的这题,但是就算知道是用区间dp做也划分不好状态,后来瞄了一眼状态划分,顿时被这题的思路惊呆了,将栈的特性应用的淋漓尽致,让人叹服。
题目分析:和普通的区间dp不同,这题无论任何情况下,都设当前区间最前面的一个元素为分割点,应用了栈的特性:若第一个元素第k个出栈,则第二到k个元素肯定在第一个元素之前出栈,第k+1到最后一个元素肯定在第k个之后出栈,这样便把区间划分成了两段,以此状态依次划分,加上记忆化搜索,便能得出答案。这题的记忆化搜索也和一般区间dp不同,区间内的值会随着区间之前共取出多少元素的改变而改变,故对要记忆的区间,记录下共有多少元素在此区间之前出栈,然后下次用到该区间是和记录的出栈元素个数比较,去掉多加或多减的部分,便能完成记忆化搜索。
#include <iostream> #include <cstring> using namespace std; int dp[101][101]; int q[101]; int INF=0x3f3f3f3f; int mark[101][101]; int sum[101]; int min(int a,int b) { return a>b?b:a; } int interval(int l,int r,int k) { if (l>r) return 0; if (mark[l][r]>=0) { int a=(k-mark[l][r])*(sum[r]-sum[l-1])+dp[l][r]; return a; } dp[l][r]=INF; for (int i=1;i<=r-l+1;i++) { int p=interval(l+1,l+i-1,k)+interval(l+i,r,k+i)+(i+k-1)*q[l]; dp[l][r]=min(dp[l][r],p); } mark[l][r]=k; return dp[l][r]; } int main() { int T; cin>>T; for (int r=1;r<=T;r++) { int n; cin>>n; sum[0]=0; for (int i=1;i<=n;i++) { scanf("%d",&q[i]); sum[i]=sum[i-1]+q[i]; } memset (dp,0,sizeof(dp)); memset(mark,-1,sizeof(mark)); interval(1,n,0); printf("Case #%d: %d\n",r,dp[1] ); } }
相关文章推荐
- 从市场的角度来看技术的学习
- Android 资源文件中@、@android:type、@*、?、@+含义和区别
- 从市场的角度来看技术的学习
- Tomcat直接访问ip-不输入项目名称和端口号-访问指定web项目的方法
- 第一周 项目一 枚举坐标点
- 高级算法课程(一):模拟退火算法SA()及其C++代码
- OracleDesigner学习笔记1――安装篇
- 科技改变生活,阵痛在所难免
- 扩充BusyBox,追加Applet的方法
- 上瘾:如何打造习惯养成中的产品(奖励篇)
- 游戏协议加密及身份验证
- Confluence 最近使用的标签(Recently Used Labels)宏
- 99刀299刀 开发者账户 区别
- 如何编写高质量的JavaScript代码
- 0049 用jad对class文件进行(批量)反编译【基础】
- C++拷贝构造函数及重写operator =的区别
- a++为什么不能作为左值?
- iOS中控件的Frame属性和Bounds属性的区别
- android四大组件之activity
- 选择网站关键词以及关键词分析优化