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. Mysql主从(主从不同步解决办法,常见问题及解决办法,在线对mysql做主从复制)

    一.主从不同步解决办法 先上Master库: mysql>show processlist; 查看下进程是否Sleep太多.发现很正常. show master status; 也正常. mys ...

  2. Chrome应用技巧之颜色拾取

    之前在Chrome应用店找了个插件实现拾色功能.并且很不理想.不知道是不是曾经Chrome自带的开发工具没提供到拾色功能还是我没发现.今天无意中发现Chomer自带的开发工具可拾色,请看以下的GIF动 ...

  3. 函数参数中“x++”造成的运算无效测试

    可能以前书上都有说过,当时没在意 只有在实际项目中才会遇到因这个问题导致的Bug 2017/2/26日补充:实际上比较通用的做法是 ++tmp1,这样也可以做到自增 ; ); Console.Writ ...

  4. redis命令_SETNX

    SETNX key value 将 key 的值设为 value ,当且仅当 key 不存在. 若给定的 key 已经存在,则 SETNX 不做任何动作. SETNX 是『SET if Not eXi ...

  5. iOS开发多线程篇 07 —GCD的基本使用

    iOS开发多线程篇—GCD的基本使用 一.主队列介绍 主队列:是和主线程相关联的队列,主队列是GCD自带的一种特殊的串行队列,放在主队列中得任务,都会放到主线程中执行. 提示:如果把任务放到主队列中进 ...

  6. javascript构造函数的理解

    构造函数是在javascript文档的创建对象当中提到的,主要目的是为了解决代码复用,能够大量产生同类型而多作用的方法 在javascript中给出了几种创建对象的模式: 1.对象字面量 例: var ...

  7. Win7下 OpenCV+Qt开发环境搭建

    1.所需软件工具: (1)OpenCV开发库,2.4.9版:包括源文件(source文件夹)和编译后的文件(build文件夹),但最好自己使用CMake又一次编译.否则easy出错. (2)Qt Cr ...

  8. JQuery File Upload 插件 出现 “empty file upload result” 错误的解决方案。

    本例中采用的是 JQuery File Upload + ASP.NET 的方式, Google了大半天基本没有找到合理的解决方案,倒是在 NodeJS的一遍博客中找到了灵感:http://www.i ...

  9. 基于ZK的分布式锁实现

    import java.util.concurrent.TimeUnit; import org.apache.curator.framework.CuratorFramework; import o ...

  10. Python爬虫框架--pyspider初体验

    之前接触scrapy本来是想也许scrapy能够让我的爬虫更快,但是也许是我没有掌握scrapy的要领,所以爬虫运行起来并没有我想象的那么快,看这篇文章就是之前使用scrapy的写得爬虫.然后昨天我又 ...