http://blog.csdn.net/wangdan11111/article/details/45032519

http://acm.nyist.net/JudgeOnline/problem.php?pid=737

2015-04-13 21:36 406人阅读 评论(0) 收藏 举报
 分类:
NYOJ(12)  动态规划(13) 

版权声明:本文为博主原创文章,未经博主允许不得转载。

目录(?)[+]

好吧, 也别着急,动态规划本来就是很难理解的, 你们也做了一些动态规划的提了。 也了解DP本来就很难想, 我开始做的时候也很慢, 也是自己理解了好久, 开始都这样。 我讲的也有点快, 那块没理解, 欢迎随时来问。 我那讲的不好理解, 就指出来, 我改进。大家相互学习。

DP一般最难想的就是状态转移方程。

区间型DP一般(也有例外)都是从小的区间开始求最优解,然后不断扩大所求的区间,而求大区间时所用到的小区间前面已经求过了。so直接用就行啦。

区间内枚举最后一次的位置, 所以说区间动规一般都是三层for循环, 前两层用来控制区间长度, 最后一层用来枚举最后一次的位置, 还有需要注意的是区间用从小到大, 因为动态规划就是后面的用到前面的出的结果递推后面的结果。 dp[i][j] 表示从第 i 堆合并到第 j 堆的最小代价,

sum[i][j] 表示第 i 堆到第 j 堆的石子总和,则动态转移方程:dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + sum[i][j]) (i <= k <= j - 1)。

  1. //关键的一块::合并i到j的所有石子。那前一状态一定是两堆石子。
  2. //这步我们就枚举所有可能的位置(两堆石子分开的位置)
  3. for(int k = i; k < j; k++)
  4. {
  5. if(dp[i][j] > dp[i][k] + dp[k+1][j] + sum[i][j])
  6. dp[i][j] = dp[i][k] + dp[k+1][j] + sum[i][j];
  7. }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

额。。举个例子吧:4个数(1,2,3, 4) 

某区间(i到j)相距为1时 d = 1 可求出f[1][2] = 3; f[2][3] = 5; f[3][4] = 7; 

d = 2时 , f[1][3] = min(f[1][2] + f[3][3], f[1][1] + f[2][3])+sum[1][3]= 9; (这里f[3][3] = 0,应为合并自己没花费)。同理f[2][4] = 14; 

d = 3时:f[1][4] = 19; 

枚举前一状态 f[1][4] = min(f[1][1]+f[2][4], f[1][2]+f[3][4], f[1][3] + f[4][4]) + sum[1][4];到这有点眉目没。

耐心点看看!! 

还有一点需要注意, 他的最后结果是用的总代价, 所以dp的结果要来自合并当前这次的代价和 当前这次以前的总代价。


  1. #include<iostream>
  2. #include<cstdio>
  3. #include<string.h>
  4. using namespace std;
  5. const int N = 220;
  6. const int M = 10e9;
  7. int n, s[N][N], a[N], f[N][N];
  8. int main()
  9. {
  10. while(scanf("%d", &n) != EOF)
  11. {
  12. memset(s, 0, sizeof(s));
  13. memset(a, 0, sizeof(a));
  14. memset(f, 0, sizeof(f));
  15. for(int i = 1; i <= n; i++)
  16. scanf("%d", &a[i]);
  17. for(int i = 1; i <= n; i++)
  18. {
  19. for(int j = i; j <= n; j++)
  20. {
  21. f[i][j] = M;//要求最小花费, 所以把最初值置为一个大数
  22. for(int k = i; k <= j; k++)
  23. s[i][j] = s[i][j] + a[k];
  24. }
  25. }
  26. for(int i = 1; i <= n; i++)
  27. f[i][i] = 0;//自己到自己不用合并, 所以花费为0;
  28. for(int i = 1; i < n; i++)
  29. {
  30. for(int j = 1; j <= n-i; j++)
  31. {
  32. for(int k = j; k <= i + j - 1; k++)
  33. {
  34. //不断更新最小值
  35. if(f[j][i+j] > f[j][k] + f[k+1][i+j]+s[j][i+j])
  36. f[j][i+j] = f[j][k] + f[k+1][i+j]+s[j][i+j];
  37. }
  38. printf("f[%d][%d] = %d\n", j, i+j, f[j][i+j]);
  39. }
  40. }
  41. printf("%d\n", f[1][n]);
  42. }
  43. return 0;
  44. }
  45.  
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

递归方法


  1. #include<iostream>
  2. #include<cstdio>
  3. #include<string.h>
  4. using namespace std;
  5. const int N = 220;
  6. const int M = 10e9;
  7. int n, s[N][N], a[N], d[N][N];
  8. void sum()
  9. {
  10. for(int i = 1; i <= n; i++)
  11. {
  12. for(int j = i; j <= n; j++)
  13. {
  14. for(int k = i; k <= j; k++)
  15. s[i][j] += a[k];
  16. // printf("s[%d][%d] = %d\n", i, j, s[i][j]);
  17. }
  18. }
  19. }
  20. int dp(int x, int y)
  21. {
  22. if(d[x][y] != 10e8) return d[x][y];
  23. for(int i = x; i < y; i++)
  24. d[x][y] = min(d[x][y], dp(x, i) + dp(i+1, y) + s[x][y]) ;
  25. // printf("d[%d][%d] = %d\n", x, y, d[x][y]);
  26. return d[x][y];
  27. }
  28. int main()
  29. {
  30. while(scanf("%d", &n) != EOF)
  31. {
  32. memset(s, 0, sizeof(s));
  33. for(int i = 1; i <= n; i++)
  34. for(int j = 1; j <= n; j++)
  35. d[i][j] = 10e8;
  36. for(int i = 1; i <= n; i++)
  37. scanf("%d", &a[i]);
  38. sum();
  39. for(int i = 1; i <= n; i++)
  40. d[i][i] = 0;
  41. int ans = dp(1, n);
  42. printf("%d\n", ans);
  43. }
  44. return 0;
  45. }

nyoj 737 石子合并 http://blog.csdn.net/wangdan11111/article/details/45032519的更多相关文章

  1. RTP协议分析(转自:http://blog.csdn.net/bripengandre/article/details/2238818)

    RTP协议分析 第1章.     RTP概述 1.1.  RTP是什么 RTP全名是Real-time Transport Protocol(实时传输协议).它是IETF提出的一个标准,对应的RFC文 ...

  2. Win32消息循环机制等【转载】http://blog.csdn.net/u013777351/article/details/49522219

    Dos的过程驱动与Windows的事件驱动 在讲本程序的消息循环之前,我想先谈一下Dos与Windows驱动机制的区别: DOS程序主要使用顺序的,过程驱动的程序设计方法.顺序的,过程驱动的程序有一个 ...

  3. 转-spring-boot 注解配置mybatis+druid(新手上路)-http://blog.csdn.net/sinat_36203615/article/details/53759935

    spring-boot 注解配置mybatis+druid(新手上路) 转载 2016年12月20日 10:17:17 标签: sprinb-boot / mybatis / druid 10475 ...

  4. http://blog.csdn.net/milton2017/article/details/54406482

    转自:python 把几个DataFrame合并成一个DataFrame——merge,append,join,conca http://blog.csdn.net/zutsoft/article/d ...

  5. git创建使用1https://blog.csdn.net/Hanani_Jia/article/details/77950594

    这篇文章是我自己写的关于GitHub的内容,从我刚听到这个直到设置成功每一步都有详细的步骤来解释,其中有一些截图或者代码来自于网上. 首先,我先对GitHub来一个简单的介绍,GitHub有一个很强大 ...

  6. http://blog.csdn.net/LANGXINLEN/article/details/50421988

    GitHub上史上最全的Android开源项目分类汇总 今天在看博客的时候,无意中发现了 @Trinea在GitHub上的一个项目 Android开源项目分类汇总, 由于类容太多了,我没有一个个完整地 ...

  7. 线段树详解 (原理,实现与应用)(转载自:http://blog.csdn.net/zearot/article/details/48299459)

    原文地址:http://blog.csdn.net/zearot/article/details/48299459(如有侵权,请联系博主,立即删除.) 线段树详解    By 岩之痕 目录: 一:综述 ...

  8. MVC和WebApi 使用get和post 传递参数。 转载https://blog.csdn.net/qq373591361/article/details/51508806

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq373591361/article/details/51508806我们总结一下用js请求服务器的 ...

  9. http://blog.csdn.net/java2000_wl/article/details/8627874

    http://blog.csdn.net/java2000_wl/article/details/8627874

随机推荐

  1. 用django框架做自己的blog

    说明:我的系统环境是ubuntu 14.10版本的,整理这篇博客,主要是自己记性太不好了,老忘东西,教训一下自己.哈哈 参考文章 createing blog 1,part-1-creating-bl ...

  2. 用jquery实现小火箭到页面顶部的效果

    恩,不知道之前在哪看过一个页面效果就是如果页面被滑动了就出现一个小火箭,点击这个小火箭就可以慢慢回到页面顶部,闲的没事,自己搞了一下 需要引入jquery 代码和布局都很简单 <!DOCTYPE ...

  3. python作业类Fabric主机管理程序开发(第九周)

    作业需求: 1. 运行程序列出主机组或者主机列表 2. 选择指定主机或主机组 3. 选择让主机或者主机组执行命令或者向其传输文件(上传/下载) 4. 充分使用多线程或多进程 5. 不同主机的用户名密码 ...

  4. RMQ之ST求区间最大值

    题目链接:https://cn.vjudge.net/problem/HRBUST-1188 每一次按照二进制的方式进行更新,二维数组dp [i] [j],i表示下标,j表示从i 开始的往后移动2的j ...

  5. 离散化&&逆序数对

    题目:http://www.fjutacm.com/Problem.jsp?pid=3087 #include<stdio.h> #include<string.h> #inc ...

  6. arch安装完成之后不能使用笔记本自带的无线网卡

    问题描述如下 我笔记本的wifi网卡识别不了,不知道为什么?? 使用ifconfig -a 只列出了有线网卡以及外接的无线网卡如下 enp4s0f1: flags=<UP,BROADCAST,M ...

  7. Supply

    Supplier创建一个Supply Supply有tap或emit方法. 可以这样理解: Supplier创建一个工厂 Supply 用tap创建流水线 emit向流水线上传送加工品进行加厂 my ...

  8. django【ORM】 通过外键字段找对应类

    两个方法其实是一种,用哪个都行,看实例:   方法一: 从list_filter中的字符串,找到model对象的字段,然后得到这个外键对应的类 循环,把list_filter中对应的类所有对象 方法二 ...

  9. Java 序列化工具类

    import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sun.misc.BASE64Decoder; import sun.m ...

  10. python代码这样写会更优雅

    1.链式比较操作 age = 18 if age > 18 and age < 60: print("young man") pythonic if 18 < a ...