
Volume 5.0 Dynamic Programming
文章平均质量分 52
深蓝色的猫
一个努力成长为大牛的蒟蒻程序媛
展开
-
UVa OJ 111
1、就是一个最长公共子序列问题。但是注意题目给出的信息,要把它按历史事件排序(标准答案和学生答案都要)才行。举个例子,事件一发生在第三个和事件三发生在第一个,两者是不等价的吧?如果不理解这个,会怀疑样例是错的——实际没有。2、这是我在OJ交过的第一道DP题,还是很有纪念意义的。#include #include using namespace std;int a[30],b[3原创 2013-08-03 16:23:45 · 455 阅读 · 0 评论 -
UVa OJ 348
1、求最优矩阵链乘。本来属于经典题,但是本题有一个难点就是要输出括号表达式,用回溯法即可(写了好久),注意空格。2、交的时候忘记删除freopen了,WA了一次。。。太冤了吧。。。#include#include#includeusing namespace std;const int INF=2147483647;int d[15][15],p[15],di[15][原创 2013-08-26 14:57:18 · 321 阅读 · 0 评论 -
UVa OJ 562
1、本题可以转化为0-1背包问题,选一些硬币装在背包中,使总价值不超过sum/2的前提下价值尽量大(这里权值就是价值)。2、刚开始读入a时从a【0】开始,WA了一次,应从a【1】开始。#include #include #include using namespace std;long long d[110][50010];int a[110];int main()原创 2013-08-26 12:15:19 · 319 阅读 · 0 评论 -
UVa OJ 624
1、这是个0-1背包本题,加上一个打印路径,就不太好想。。。要和一维的时候区分开,p数组应是个二维数组才行。因为相同物品可能在不同状态下使用:例如一个背包剩余j1空间,一个剩余j2空间。打印路径时务必考虑剩余空间。刚开始没加(m==num+1)的情况,WA了一次。具体见代码。#include #include #include using namespace std;long原创 2013-08-26 17:52:20 · 373 阅读 · 0 评论 -
UVa OJ 147
1、在本地调试的时候,用I64d,在UVa上用lld。2、本题数据很大,用最大的数据测试的话发现不得不用long long。3、要注意四舍五入,否则输入6美分的时候会出错。#include #include #include using namespace std;long long d[30010][12];int v[11]={10000,5000,2000,1原创 2013-08-15 17:27:54 · 356 阅读 · 0 评论 -
UVa OJ 10130
1、刚开始看到这道题吓坏了,以为是多个0-1背包,其实是“多次”0-1背包,因为超市的物品是无限的。2、注意状态的选取,尤其是第一个参数,状态转移的时候不是dp(n-1,mw-w[i]),而是dp(i,mw-w[i]),否则因为记忆化搜索的缘故会引起混乱(状态全乱了)。#include#include#includeusing namespace std;int v[101原创 2013-09-03 14:06:26 · 346 阅读 · 0 评论 -
UVa OJ 531
1、唉,这一道又做了好久好久啊~2、其实也没有什么,最长公共子序列的变体,但是唯一有难度的就是要输出所求序列,这就需要记录“规划方向”,二维的规划方向比一维的要难,不过理解了就好了,三个方向用0,-1,1表示。3、注意记录方向的语句是无条件执行的,不是大于ans的时候才执行。#include#include#includeusing namespace std;char原创 2013-09-03 22:59:37 · 433 阅读 · 0 评论 -
UVa OJ 10285
1、刚开始以为DP会陷入死循环,其实不会,因为递归的条件是有高度差,所以一个格子不可能调用它来自的格子,也就不会产生无限调用。2、注意递归前要判断格子合不合法,否则会数组越界。#include#include#includeusing namespace std;int a[110][100],d[110][110],N,r,c;bool is_valid(int i,原创 2013-11-01 00:42:06 · 352 阅读 · 0 评论 -
UVa OJ 437
1、刚开始确实看到每种砖的数量是无限的,但读完题就忘了,然后各种考虑重复情况啊。。。其实不用,既然砖的数量是无限的,题目就被大大简化了。每次只要像上一题“滑雪问题”一样,先判断放法合不合法,然后递归即可。注意判断的时候要考虑两种情况(横放和竖放)。其实这个我也考虑到了,但是读完题就忘了。。。是否应该拿张纸,把题目的关键点一一记下,就像这道描述很长的题目一样?2、比较高兴的是一次AC~说不定DP原创 2013-11-01 11:35:44 · 300 阅读 · 0 评论 -
UVa OJ 10635
#include#include#includeusing namespace std;const int maxn=250*250;const int INF=1000000000;int s[maxn],g[maxn],d[maxn];int num[maxn];int main(){ int T; scanf("%d",&T); for原创 2013-08-22 00:21:33 · 337 阅读 · 0 评论 -
UVa OJ 103
1、又是一道DP,一次AC,发现DP题只要你会做就不会错。。。这点比那些用BT数据坑人的模拟题好多了。2、本题可以转化为DAG上的最长路问题,易错的地方主要有:k和n容易搞混,k是盒子数而n是盒子维数,这让习惯以n来计数的我很不适应;最佳答案要单独用path数组保存,否则会被覆盖;注意交题的时候把freopen给注释掉。#include#include#includeusing原创 2013-08-05 15:12:03 · 414 阅读 · 0 评论 -
UVa OJ 10405
1、LCS问题,注意有个陷阱就是可能有空串。2、想把原来写的程序复制粘贴来用居然不行,因为原来写的是从1开始的,现在是从0开始的,所以要修改。以后把这个当模板吧!3、scanf不能读回车。#include#include#include#includeusing namespace std;int d[1010][1010];char a[1010],b[101原创 2013-08-05 17:48:54 · 435 阅读 · 0 评论 -
UVa OJ 674
1、刚拿到这题的时候,我的思路是设计一个一维数组d,用来保存金钱为num时的最优解,但是调试的时候发现对于6这个数字,可以有3种换法:1 1 1 1 1 1或5、1或1 、5,明显5、1和1、5重复了。2、我想了很久,也没有想出如何避免这种情况,后来阅读另一位ACMer的博客才知道,可以按顺序分割。3、先举个例子,比如从1,2,3中任取两数,求有多少种组合,一共是三种,可以是1,2;2,3原创 2013-08-05 21:45:41 · 388 阅读 · 0 评论 -
UVa OJ 10003
1、本题刚开始TLE。我认为dp【0】【N】即为区间(0,L)上的最小费用,虽然实际上运算次数并不多,但是每次初始化时,要初始化一个1000*1000的数组,这样测试数据一多就很容易超时。仔细想想,其实1000*1000的数组很多地方都没有用到,故改成50*50的数组即可,省了一大笔空间,也就省了一大笔初始化的时间。#include #include #include using原创 2013-08-08 16:48:32 · 410 阅读 · 0 评论 -
UVa OJ 10131
1、刚开始没找好状态,dp(i)应为从i结点出发的最长下降子序列长度,而不是i结点及其以后的最长下降子序列长度。记忆化搜索保证了不超时,所以放心枚举。2、运算符重载后用sort函数做一个预处理,使所求数据变成对于w升序对于s降序,然后求最长下降子序列即可,用fa数组保存路径。3、题目可能有多种答案,任意输出一种即可。#include#include#includeusing原创 2013-08-11 17:48:03 · 367 阅读 · 0 评论 -
UVa OJ 116
1、用long long保存。2、三个方向取最小,别忘了加上本身格子里的值。3、-和4、题目要求字典序最小,所以单独考虑相等的时候。5、利用循环队列的思想,因为可以超出范围,所以先搜索到的不一定是字典序最小(如按上中下顺序搜索的话,先搜到4,再搜到0,再搜到1,但是4>0),所以要单独写一个比较语句。#include#include#includeusing nam原创 2013-08-08 19:31:02 · 391 阅读 · 0 评论 -
UVa OJ 10066
1、LCS问题,一次AC~#include#include#includeusing namespace std;int d[110][110];int a[110],b[110];int dp(int i,int j){ if(i int &ans=d[i][j]; if(ans>0)return ans; if(a[i]==b原创 2013-08-11 20:39:00 · 323 阅读 · 0 评论 -
UVa OJ 10192
1、这道题毫无疑问是LCS,但是刚开始连续TLE把我弄得莫名其妙,后来把d的初值从0改为-1就过了,但是我还是不知道为什么。。。总之赋值为-1比较安全吧。#include#include#includeusing namespace std;int d[105][105];char a[105],b[105];int dp(int i,int j){ if(i原创 2013-08-11 23:58:54 · 468 阅读 · 0 评论 -
UVa OJ 357
1、又是分硬币问题。。。一次AC~#include #include #include using namespace std;long long d[30010][12];int v[5]={50,25,10,5,1};long long dp(int num,int pre){ long long &ans=d[num][pre]; if(ans>0原创 2013-08-26 11:07:08 · 327 阅读 · 0 评论 -
UVa OJ 10404
1、比较像巴什博弈。。。数学真的挺重要。用递推做,只要让当前石子数减去合法取法,得到的数值是必败的,那就说明这样能使对手达到必败局面,则当前是必胜局面。#include#includeusing namespace std;int a[15],n,m;bool state[1000010];int main(){ while(scanf("%d%d",&n,&m)=原创 2013-11-08 23:18:54 · 343 阅读 · 0 评论