POJ3176

Cow Bowling

题意

输入一个n层的三角形,第i层有i个数,求从第1层到第n层的所有路线中,权值之和最大的路线。

规定:第i层的某个数只能连线走到第i+1层中与它位置相邻的两个数中的一个。

思路

最显而易见的是使用二维数组动态规划计算。

比如dp[i][j]表示以第i行j列的位置作为终点的路线的最大权值。 (注意区分初始化时的意义)

那么dp[i][j]的最大值取决于dp[i-1][j-1]和dp[i-1][j],从这两者之间筛选出最大值,加到dp[i][j]上,即为dp[i][j]的最大权值。

最后只要比较第n行中所有位置的权值dp[n][j],最大的一个即为所求。

但其实用一维数组也能够完成要求,具体请看我的代码。

代码

Source Code

Problem: 3176       User: liangrx06
Memory: 248K Time: 79MS
Language: C++ Result: Accepted
Source Code
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std; const int N = 350; int main(void)
{
int n;
int a[N], dp[N]; cin >> n;
dp[0] = 0;
for (int i = 0; i < n; i ++) {
for (int j = 0; j <= i; j ++) {
scanf("%d", &a[j]);
}
for (int j = i; j >= 0; j --) {
if (j == 0)
dp[j] = dp[j] + a[j];
else if (j == i)
dp[j] = dp[j-1] + a[j];
else
dp[j] = max(dp[j], dp[j-1]) + a[j];
}
} int sum = 0;
for (int i = 0; i < n; i ++)
sum = max(dp[i], sum);
printf("%d\n", sum); return 0;
}

POJ2229

Sumsets

题意

求把一个整数分解为2的幂的和共有几种方案。

例如整数7的分解有6种方案:

7=1+1+1+1+1+1+1

7=1+1+1+1+1+2

7=1+1+1+2+2

7=1+1+1+4

7=1+2+2+2

7=1+2+4

思路

这种题通常都是用递归来解的。假设n对应的分解方案数为f(n)首先按照n为奇数和偶数的情况分别分析:

n为奇数时,分解式中一定含有1,去掉这个1,剩下的分解式的和为n-1,也就是说,f(n) = f(n-1);

n为偶数时,分解式中若含有1,方案数为f(n-1),若不含有1,将分解式中的数都除以2,其和对应于n/2,也就是说方案数为f(n/2),所以f(n) = f(n-1)+f(n/2)。

如此由n=1的初始条件递归求解即可,也可以说是动态规划。

但是这个题我WA了三次,后来发现这个题的答案会超出long long的表示范围,需要取余,改了好几次才AC。所以一定要注意答案的范围。

代码

Source Code

Problem: 2229       User: liangrx06
Memory: 4136K Time: 125MS
Language: C++ Result: Accepted
Source Code
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std; const int N = 1000000; int main(void)
{
int n;
int a[N+1]; cin >> n;
a[0] = 1;
for (int i = 1; i <= n; i ++) {
if (i&1)
a[i] = a[i-1];
else
a[i] = a[i/2] + a[i-1];
a[i] %= 1000000000;
}
printf("%lld\n", a[n]); return 0;
}

POJ2385

Apple Catching

题意

2棵苹果树在T分钟内随机由某一棵苹果树掉下一个苹果,奶牛站在树#1下等着吃苹果,它最多愿意移动W次,问它最多能吃到几个苹果。

思路

动态规划题。状态空间主要决定于W,以dp[i][j][k]表示第i+1分的时候经过j次移动站在了k+1树下能吃到的最大苹果数,然后搜索所有的ijk组合,更新dp。

实际上我使用的数组是dp[i&1][j][k],用i&1的目的是降低空间复杂度,dp数组大小降为原来的2/T。

代码

Source Code

Problem: 2385       User: liangrx06
Memory: 248K Time: 16MS
Language: C++ Result: Accepted
Source Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int T = 1000;
const int W = 30; int main(void)
{
int t, w;
int a[T+1];
int dp[2][W+1][2]; cin >> t >> w;
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= t; i ++) {
scanf("%d", &a[i]);
a[i] --;
for (int j = 0; j <= w; j ++) {
dp[i&1][j][a[i]] = dp[(i-1)&1][j][a[i]] + 1;
dp[i&1][j][(a[i]+1)&1] = dp[(i-1)&1][j][(a[i]+1)&1];
if (j > 0) {
dp[i&1][j][a[i]] = max(dp[i&1][j][a[i]],
dp[(i-1)&1][j-1][(a[i]+1)&1] + 1);
dp[i&1][j][(a[i]+1)&1] = max(dp[i&1][j][(a[i]+1)&1],
dp[(i-1)&1][j-1][a[i]]);
}
}
}
int res = 0;
for (int j = 0; j <= W; j ++) {
res = max(res, dp[t&1][j][0]);
res = max(res, dp[t&1][j][1]);
}
printf("%d\n", res); return 0;
}

POJ3616

Milking Time

题意

奶牛Bessie在0~N时间段产奶。农夫约翰有M个时间段可以挤奶,时间段f,t内Bessie能挤到的牛奶量e。奶牛产奶后需要休息R小时才能继续下一次产奶,求Bessie最大的挤奶量。

思路

定义dp[i]表示第i个时间段(注意此处的第i个时间段不等同于第i次)挤奶能够得到的最大值,拆开来说,就是前面 i – 1个时间段任取0到i – 1个时间段挤奶,然后加上这个时间段(i)的产奶量之和。

dp[i]满足如下递推关系:

第i个时间段挤奶的最大值 = 前 i – 1 个时间段挤奶的最大值的最大值 + 第i次产奶量。

代码

Source Code

Problem: 3616       User: liangrx06
Memory: 184K Time: 0MS
Language: C++ Result: Accepted
Source Code
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std; const int M = 1000; struct Time {
int f, e, v;
}; bool cmp(const Time& a, const Time& b)
{
return a.f < b.f;
} int main(void)
{
int n, m, r;
Time t[M];
int dp[M+1];
int ans = 0; scanf("%d%d%d", &n, &m, &r);
for (int i = 0; i < m; i ++)
scanf("%d%d%d", &t[i].f, &t[i].e, &t[i].v);
sort(t, t+m, cmp); memset(dp, 0, sizeof(dp));
for (int i = 0; i < m; i ++) {
dp[i] = t[i].v;
for (int j = 0; j < i; j ++) {
if (t[i].f >= t[j].e + r)
dp[i] = max(dp[i], dp[j] + t[i].v);
}
ans = max(ans, dp[i]);
}
printf("%d\n", ans); return 0;
}

POJ3280

Cheapest Palindrome

题意

有一个由n个小写字母组成的,长度为m的字符串,可以对其通过增加字符或者删除字符来使其变成回文。而增加或者删除字符都有一个花费,求解使该字符串变成回文的最小花费。

思路

动态规划。dp[i][j]表示串str[i~j]变成回文的最小代价,故状态转移方程为:
当str[i] == str[j]时 dp[i][j] = dp[i+1][j-1];
当str[i] != str[j]时 dp[i][j] = min( dp[i+1][j]+add[str[i]-'a'], dp[i][j-1]+add[str[j]-'a'], dp[i+1][j]+del[str[i]-'a'], dp[i][j-1]+del[str[j]-'a']);

更详细的分析(以下内容转自小鱼的博客):

其实dp很难逃出3种思路:
1、一维线性dp:每次考虑i时,选择最优子问题要么在i-1,要么在1...i-1里;
2、二维线性dp:考虑(i,j)子问题时,选择最优子问题要么在(i+1,j)、(i,j-1),要么在i<= k <=j,在k里;
3、树形dp:考虑i节点最优时,选择子节点最优,一般融合了01背包dp的双重dp。
上面3种模式也是我在做题后才发现的。
这个dp题其实就可以仿照第2中思路。
假设一个字符串Xx....yY;对于求这个字符串怎么求呢?
分4种情况讨论:
1、去掉X,取x....yY回文;
2、去掉Y,取Xx....y回文;
3、在左边加上X,取Xx....yYX回文;
4、在右边加上Y,取YXx....y回文。
至于去掉X、Y肯定没有第1、2中情况合算;加上X、Y肯定没有第3、4中情况合算。
因此令dp[i][j]为i...j要变成回文字符串的最小代价。
方程:
dp[i][j] = min{ dp[i+1][j] + {去掉X的代价},dp[i+1][j] + {加上X的代价},dp[i][j-1]+ {去掉Y的代价},dp[i][j-1] +{加上Y的代价}};
其实分析发现,对于X而言,只要去 去掉 和加上 X 最小代价就行(因为前面dp串一样),Y同理。
因此最后得出:
dp[i][j] = min{ dp[i+1][j] +min{ {去掉X的代价}, {加上X的代价}},dp[i][j-1]+min{ {去掉Y的代价}, {加上Y的代价}}};
dp时候还有些注意事项:
比如当X和Y字符一样时,则在dp时必须先为x...y的最小代价。

代码

Source Code

Problem: 3280       User: liangrx06
Memory: 15852K Time: 172MS
Language: C++ Result: Accepted
Source Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int M = 2000; int dp[M+1][M+1]; int main(void)
{
int i, j, k, n, m;
char s[M+1];
int add[26], del[26]; scanf("%d%d%s", &n, &m, s);
for (i = 0; i < n; i ++) {
char c[2];
scanf("%s", c);
scanf("%d", &add[c[0]-'a']);
scanf("%d", &del[c[0]-'a']);
} memset(dp, 0, sizeof(dp));
for (k = 0; k < m; k ++) {
for (i = 0; i < m-k; i ++) {
j = i + k;
if (s[i] == s[j])
dp[i][j] = dp[i+1][j-1];
else {
dp[i][j] = min(dp[i+1][j] + add[s[i]-'a'], dp[i+1][j] + del[s[i]-'a']);
dp[i][j] = min(dp[i][j], dp[i][j-1] + add[s[j]-'a']);
dp[i][j] = min(dp[i][j], dp[i][j-1] + del[s[j]-'a']);
}
}
}
printf("%d\n", dp[0][m-1]); return 0;
}

《挑战程序设计竞赛》2.3 动态规划-基础 POJ3176 2229 2385 3616 3280的更多相关文章

  1. 《挑战程序设计竞赛》2.3 动态规划-优化递推 POJ1742 3046 3181

    POJ1742 http://poj.org/problem?id=1742 题意 有n种面额的硬币,面额个数分别为Ai.Ci,求最多能搭配出几种不超过m的金额? 思路 据说这是传说中的男人8题呢,对 ...

  2. Aizu 2249Road Construction 单源最短路变形《挑战程序设计竞赛》模板题

    King Mercer is the king of ACM kingdom. There are one capital and some cities in his kingdom. Amazin ...

  3. 挑战程序设计竞赛》P345 观看计划

                                                 <挑战程序设计竞赛>P345 观看计划 题意:一周一共有M个单位的时间.一共有N部动画在每周si时 ...

  4. POJ 2386 Lake Counting 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=2386 <挑战程序设计竞赛>习题 题目描述Description Due to recent rains, water has ...

  5. poj 3253 Fence Repair 贪心 最小堆 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=3253 题解 本题是<挑战程序设计>一书的例题 根据树中描述 所有切割的代价 可以形成一颗二叉树 而最后的代价总和是与子节点和深 ...

  6. 《挑战程序设计竞赛》2.3 动态规划-进阶 POJ1065 1631 3666 2392 2184(5)

    POJ1065: Description There is a pile of n wooden sticks. The length and weight of each stick are kno ...

  7. 《挑战程序设计竞赛》 4.1.1 矩阵 P286

    想写几篇挑战的感悟,也有助于自己理解这本书.但这上面大多贴的是书上的代码,主要是为了用的时候后直接复制就好了,这样就很方便了,就相当于黑盒模板了. 1.线性方程组 /** \brief 高斯消元法 * ...

  8. 《挑战程序设计竞赛》P196 铺砖问题

    题意:给定n*m格子,每个格子被染成了黑色或者白色,现在要用1*2的砖块覆盖这些格子,块与块不得重叠,且覆盖所有的白色格子,但不覆盖任意一个黑色格子,求一共有多少种覆盖方法. 思路:书上给的思路太巧妙 ...

  9. poj 1979 Red and Black 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=1979 Description There is a rectangular room, covered with square tiles ...

随机推荐

  1. unity, StopAllCoroutines导致bug的解决办法

    StopAllCoroutines有时候不用不行. 但只要一用,就可能导致无穷无尽的bug. 原因是StopAllCoroutines会将当前脚本中所有coroutines都停掉,而没法做到只停掉我们 ...

  2. Sublime Text 2 和 Verilog HDL

    Sublime Text 2 和 Verilog HDL Date  Fri 04 July 2014 Tags Sublime Text / Vivado Sublime Text 代码编辑器之于程 ...

  3. RCU

    RCU(read-copy-update)同步机制.R(Read):读者不需要获得任何锁就可访问RCU保护的临界区:C(Copy):写者在访问临界区时,写者“自己”将先拷贝一个临界区副本,然后对副本进 ...

  4. SPI—读写串行 FLASH

    SPI协议简介SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC. LCD ...

  5. string 大小写转换

      STL的algorithm库确实给我们提供了这样的便利,使用模板函数transform可以轻松解决这个问题,开发人员只需要提供一个函数对象,例如将char转成大写的toupper函数或者小写的函数 ...

  6. Yii2 Restful API 原理分析

    Yii2 有个很重要的特性是对 Restful API的默认支持, 通过短短的几个配置就可以实现简单的对现有Model的RESTful API 参考另一篇文章: http://www.cnblogs. ...

  7. 【Mac + Appium + Python3.6学习(四)】之常用的IOS自动化测试API总结

    环境: Appium:1.9.1 Appium-desktop:1.7.1 Xcode:10.0 IOS:iPhone5S(10.3.3) Mac:10.13.6 ①获取手机屏幕size:长.宽 &l ...

  8. RMAN 总括 组成 配置 检测

    RMAN 组件: 1. RMAN 执行程序, 也就是RMAN 命令. 2. Server session : 服务器上的进程, 是真正用来干活的. 3. Target database: 你想要进行备 ...

  9. 用Eclipse的tomcat插件启动tomcat时报错:

    用Eclipse的tomcat插件启动tomcat时报错: FATAL ERROR in native method: JDWP No transports initialized, jvmtiErr ...

  10. easyui menu 添加hideItem/showItem 方法

    $.extend($.fn.menu.methods,{ showItem:function(jq,text){ return jq.each(function(){ var item = $(thi ...