随笔分类 -  动态规划

摘要:题意:有这样的一个天平,关于天平的中心两边有一些钩子,钩子有一个属性就是离中心的距离。题中给定的是设中心的坐标为0,左右两边分别是负数和正数的坐标值。现在给定一些砝码,问将这些砝码都挂到天平上,使得天平保持平衡的方式有多少种?一个钩子上可以连续挂上多个砝码。解法:首先将所有钩子的坐标都加上15,然后使得最后砝码乘以坐标的总和等于总质量乘以15。这样原问题就转化为一个类似于背包的问题了。代码如下:#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>using 阅读全文
posted @ 2013-03-24 21:31 沐阳 阅读(267) 评论(0) 推荐(0)
摘要:题意:询问一个区间内要么只包含3,要么只包含8的数有多少个?解法:数位DP,可惜比赛的时候忘了怎么写了,随便写了个DP没有过,后来才调过了。正确解法是开设一个状态: f[i][0]表示剩下i+1位数中且暂时不含有3,8的满足要求的数的个数(i位数字可从全0取到全9,后同) f[i][1]表示剩下i+1位数中且暂时只含有3的满足要求的数的个数 f[i][2]表示剩下i+1位数中且暂时只含有8的满足要求的数的个数 f[i][3]表示剩下i+1位数中且已经含有3和8的满足要求的数的个数,该结果恒为零 标程的解法使用了位运算来计算状态,非常清爽。代码如下:#include <cst... 阅读全文
posted @ 2013-03-18 21:27 沐阳 阅读(647) 评论(0) 推荐(0)
摘要:题意:简单点说就是给定一棵树,每个节点都有一个权值,现在要求求出这棵树的一个联通的一枝使其权值最大。解法:设sum[i]为包含i节点在内的一枝的最大权值和,那么sum[i] = val[i] + max(0, sum[j])其中(i,j)之间存在边。当sum[j]为负数时,对父亲节点的贡献就为0了。代码如下:#include <cstdio>#include <iostream>#include <cstring>#include <cstdlib>#include <algorithm>using namespace std;int 阅读全文
posted @ 2013-03-08 14:37 沐阳 阅读(339) 评论(0) 推荐(0)
摘要:题意:给定N个点求1-N的最短路,所加的附加条件就是这N个点前A个点为村庄,后B个点为城堡。马里奥用一双靴子,能够在一定距离(L)内花0时间进行穿梭,且只有K次机会,在这种情况下,求解一个最短路。分析:首先对于如何花费这K次机会是一个动态规划的问题,因此我们需要计算出哪些边允许我们进行无代价的穿梭,由于题目还给定了穿梭只能够从某一点开始/结束,因此必须保证某一路径总长度少于L并且题目中还有一个约束条件要求该路径中间不应该有城堡,因为城堡中有陷阱不能够在穿梭的途中有陷阱。而floyd算法能够很好的就算出哪些路径能够穿梭。解法:首先通过floyd算法从1开始枚举中间点,那么由于前A个节点时村庄,路 阅读全文
posted @ 2013-03-04 21:19 沐阳 阅读(536) 评论(1) 推荐(0)
摘要:题意:给定一个规则问龟兔赛跑的结果,问题在于乌龟在何时选择充电。解法:由于最多的只有100个充电站,而影响结果的决策发生在各个充电站,因此只要考虑到达充电站时需要采取的策略。通过一个值保留到达某站并充电的最优值即可。代码如下:#include <iostream>#include <algorithm>using namespace std;// 如果两个节点连边,那么弧头上的点一定要加油class Rule {public: static int N; // 充电站的数目 static int vr, vt1, vt2; // 三个速度值 stat... 阅读全文
posted @ 2013-03-03 14:48 沐阳 阅读(370) 评论(0) 推荐(0)
摘要:这题一个很巧妙的操作就是对一个给定的区间同意将下界拿出来, 然后转化为多重背包问题. 使用二进制优化.代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>#include <iostream>#define ER 0x80808080using namespace std;/*解题:给定一个Multi数组, 一个Pairs数组, 要求出最好的Table的数组. 其中应满足这个几 个要求, 阅读全文
posted @ 2013-01-18 17:01 沐阳 阅读(738) 评论(0) 推荐(0)
摘要:这题和POJ1947类似, 同样是树形DP, 就是因为按照上题的思路写, 导致写的是非常的蛋疼. 调了几小时还是无果. 时候证明还是对状态的意义理解的不透彻.设dp[x][0][j]表示以节点x为根至多走j步并且返回x处所能够得到的最多苹果. dp[x][1][j]表示以节点x为根至多走j步不需要返回x处所能够得到的最多苹果.那么就可以得到动态转移方程(此时的dp[x][..][j]还没有完善, 需要后期处理一下):dp[x][0][j] = max( dp'[x][0][j-m] + dp[v][0][m] ); 0<=m<=j 其中dp'表示计算到上一个孩子节点 阅读全文
posted @ 2013-01-17 22:55 沐阳 阅读(325) 评论(0) 推荐(0)
摘要:这题在yefeng1627的淫威下迅速屈服. 由刚开始的一个较动态方程便很好的解决了组合问题, 再加之进一步分析, 将本来应该要的辅助状态删除, 剩下的就是一个非常优美的动态规划方程了.详见代码:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#define INF 0x3f3f3f3fusing namespace std;/*题意:给定一棵树, 现在要求从这棵树中分割出P个节点的子树, 问最少要破 阅读全文
posted @ 2013-01-17 15:21 沐阳 阅读(384) 评论(0) 推荐(0)
摘要:这题有两种解法, 一种是通过动态规划弥补一个不太成熟的贪心思路, 使得最后的结果正确. 另一种方法是构造一个更好的贪心策略.动态规划依托的结论: 每次给齐王最强的马匹配一匹田忌的马, 那么这匹马不是田忌最强的马就是最弱的马, 这一个不完善的贪心策略. 所以动态规划佐之.#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <iostream>using namespace std;/*解法:开设状态dp[i][j]表示田忌出了 阅读全文
posted @ 2013-01-17 11:31 沐阳 阅读(666) 评论(0) 推荐(0)
摘要:这题题意在代码中有解释, 求的最优值初看不太好理解. 求的是给定一个决策下的找到房子的最优期望值. 那么这题其实要做的就是一件事那就是给所有的分叉口的选择拍一个次序出来.根据这个次序我们就能够给出这只蜗牛在碰到有所情况下的唯一的一条爬行路线. 题目就是当我们安排好这样的这个次序后, 假设房子在各个叶子节点时, 需要走的路径总长最小. 这里的每一棵子树, 在枚举的过程中总是充当着不同的角色, 当枚举到的房子在自己的子树中时, 其要考虑能够安排最快的路径让蜗牛找到. 当没有在自己的子树时又不想让其放在前面让蜗牛白忙活一场. 所以综合一看, 貌似是一个很复杂的问题. 但是这题就是在如何安排子节点访问 阅读全文
posted @ 2013-01-16 21:54 沐阳 阅读(830) 评论(1) 推荐(0)
摘要:由于递推的时候依赖于三个连续层的关系.一开始想着直接三重for循环,但是这里有个问题就是上一层的0位置上包括着上上层是0和1两种可能,而后者又对当前行有约束,因此该方法不行.当然有一个办法就是增加状态数,让状态能够表示是从1还是从0转移过来的.(这题有个解法是采用多进制的状态压缩). 网上瞄了别人的一眼解题报告. 瞬间顿悟,竟然三层之间发生关系,那么就直接把连续的两层记录起来,虽然说空间上不及多进制优美. 但是却能够去描述这些个问题.代码如下:#include <cstdio>#include <cstring>#include <cstdlib>#incl 阅读全文
posted @ 2013-01-15 21:33 沐阳 阅读(473) 评论(0) 推荐(0)
摘要:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#include <iostream>#define MOD 100000000using namespace std;/*题意:给定一个矩阵,这个矩阵表示了一块土地,给定的数据只有0,1, 表示土地肥沃与否. 其中0代表不肥沃,1代表肥沃. 不肥沃的地方是不能够种植玉米的,还有一个约束就是 不能够在相邻的1种植玉米. 现在问一共有多少种种植方式. 解法:明显的状态压缩题,先dfs出一行的非 阅读全文
posted @ 2013-01-15 17:29 沐阳 阅读(445) 评论(0) 推荐(0)
摘要:这题要考虑锤子移动到网格外部的情况,否则WA,处理的方式就是行和列同时增加5(最大距离).详见代码:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#include <iostream>using namespace std;/*题意:给定一个N*N的矩阵, 然后在这个矩阵的每个格子在任意时间会出现一个鼹鼠,这个出现 出现鼹鼠的时间是输出信息所确定的. 现在你手里有一把锤子能够去锤这些鼹鼠. 你能 够移动锤子,移动的两点之间的距离不能超过 阅读全文
posted @ 2013-01-15 16:15 沐阳 阅读(454) 评论(0) 推荐(0)
摘要:详见代码:#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <algorithm>#include <iostream>#define INF 0x3f3f3f3f#define MAXN 1000005using namespace std;/*题意:给定N个柱子,现在要在这N个柱子之间摇摆,直至到达最右端的那一个柱子,问最少要 摇摆多少次. 摇摆的时机是在开始的时候或者是从某一点摇摆到某个对称的点时,保 证所有的柱 阅读全文
posted @ 2013-01-14 23:03 沐阳 阅读(826) 评论(0) 推荐(0)
摘要:详见代码:#include <cstdlib>#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;int N, M, dp[505][505];int row[505][505], col[505][505];/*题意:给定一个矩阵,矩阵中的每一个点都有两种矿产,A矿产只能够运送到上面去,B矿产只能 够运送到左边去,现在要在每个点都设置一个传送带传送带共有两种,一种是往上,一种 是往左,每个格子只能够 阅读全文
posted @ 2013-01-14 20:11 沐阳 阅读(549) 评论(0) 推荐(0)
摘要:前面自己写的动态方程转移出现了问题,还是没有考虑周全.AC代码:#include <cstdlib>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;/*题意:给定了一个字符串,问这个字符串,这个字符串是由a,b,c,...,a+N-1的字符集组成的 现在问使用使得该串成为一个回文串的最少花费是多少. 花费的定义如下: 对于每一个字符,给出添加这个字符和删除这个字符分别需要花费多少. 添加和删除 可 阅读全文
posted @ 2013-01-14 14:50 沐阳 阅读(585) 评论(0) 推荐(0)
摘要:搜索+剪枝#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#include <iostream>#define MAXN 5005using namespace std;/*题意: 给定一个行数和列数固定的网格,再给定若干个点,这些点是使用矩形上网格线交叉点的 坐标来唯一确定的R行C列的网格,左上角的坐标为(1,1)右下角的坐标为(R,C),问给定的 这些点能够组成最长可能路径是多长. 路径的定义的如下的:由若干连续且间隔相等的 点组成, 阅读全文
posted @ 2013-01-12 22:45 沐阳 阅读(485) 评论(0) 推荐(0)
摘要:这题当M=N=0的时候要输出1.000 刚写的时候默认从第二次开始取了.详见代码:#include <cstdlib>#include <cstring>#include <cstdio>#include <algorithm>#include <iostream>using namespace std;/*题意:从一个拥有无限多的盒子中拿出不同颜色的糖果,拿出任何一种颜色的概率都是1/C 每次拿出来的糖果都放在桌子上,如果有相同颜色的糖果,就把这两颗糖果吃掉.问 拿了N次后,桌子上面剩余的糖果数量为M的概率是多大 解法:设状态dp[ 阅读全文
posted @ 2013-01-11 23:21 沐阳 阅读(259) 评论(0) 推荐(0)
摘要:该题解题过程非常优美,通过位操作来维护一个可选字符集合.并且完成求并集和交集.详见代码:#include <cstring>#include <cstdio>#include <cstdlib>#include <algorithm>#include <iostream>using namespace std;/*花了大半个小时看懂了这题题意:给定N个字符串,N为2的幂,每个字符串长度为L,这N个字符串是一棵完全二叉树的叶子节点,现在问树的内部在同样要填入长度为L的字符串的情况下,最少的花费是多少,根节点是什么. 花费是这样计算的:一 阅读全文
posted @ 2013-01-11 20:34 沐阳 阅读(771) 评论(0) 推荐(1)
摘要:详见代码:#include <cstring>#include <cstdio>#include <cstdlib>#include <cmath>#include <iostream>#include <algorithm>using namespace std;int N, sum[10][10]; // sum[i][j] 表示以i,j为右下角的矩阵的和int dp[15][10][10][10][10];int tot[10][10][10][10]; // tot[m][n][i][j]记录了左上角为m, n右下 阅读全文
posted @ 2013-01-11 17:23 沐阳 阅读(306) 评论(0) 推荐(0)