随笔分类 - ACM_DP
摘要:题目链接:http://www.acdream.net/problem.php?id=1083 简单数位DP,貌似我写得太暴力了= = 1 //STATUS:C++_AC_20MS_1512KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vec
阅读全文
摘要:题目链接:http://poj.org/problem?id=2374 这个题目坑了好久啊,题意看错了,bs自己。 其实不难的,状态方程容易相处来,每个fence只有两种状态,即左边下去和右边下去,如果要知道当前状态的最优情况,就必须知道前面所有状态的最优情况,最坏情况下复杂度O(n^2)。但显然可以发现前面有很多的状态都不能到达当前状态于,因为前面的有些状态被覆盖了,于是我们可以用线段树来优化,在log(n)的时间里找到可以到达当前状态的fence。虽然在log(n)的时间里找出了状态,但是还是有比较多的状态,还可以继续优化。注意到编号为 i 的fence和所有编号为 1,2,,,,...
阅读全文
摘要:题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555我的DP方程:f[i][j]表示数的第i位以j开头的数含有49的个数,则状态转移方程为: 1.j!=4时: f[i][j]=sum{ f[i-1][k] | 0<=k<=9 } 2.j==4时:f[i][j]=sum{ f[i-1][k] | 0<=k<=9 } - f[i-1][9] + pow(10,i-2) (因为j=4时,只要i-1位为9,后面的都满足)这样的转移方程思路比较清晰,在网上看到别人的转移方程是这样的: 1.f[i][0]=10*f[i-1][0]-
阅读全文
摘要:题目链接:http://poj.org/problem?id=3345 国家之间可能存在依赖关系,可以求出每个国家向下的每种情况的最优消费,即f[u][i]表示节点为u时选择i个国家的最优消费。自底向上更新时就是分组背包问题了: f[u][i]=Min{ f[u][i],f[u][i-j]+f[v][j] | v为u的儿子节点,0<=j<=v子树的节点数 },其实本来是3维的,不过这里用滚动数组优化了。 1 //STATUS:C++_AC_16MS_588KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #inclu
阅读全文
摘要:题目链接:http://poj.org/problem?id=3280 典型的区间DP问题,fp[i][j]表示第i-j个字符经过修改后的最优值,则状态转移方程如下: f[i][j]=Min(f[i][j],f[i][j-1]+Min(cost[s[j]][0],cost[s[j]][1])); f[i][j]=Min(f[i][j],f[i+1][j]+Min(cost[s[i]][0],cost[s[i]][1])); if(s[i]==s[j]) f[i][j]=Min(f[i][j],f[i...
阅读全文
摘要:题目链接:http://poj.org/problem?id=2754 当时居然没有想到是多重背包,敲了个分组背包,TLE。。。 后来才知道可以转化为多重背包,即把每个下界L[i]放为0,上限为U[i]-L[i],就是物品的个数,价值为P[i],花费为M[i]。本来题目要求Σ(M[i]*Table[i])=0时,Σ(P[i]*Table[i])的最大值。现在Table[i]的每个值都加了-L[i],即Σ(M[i]*Table[i] + M[i]*L[i]) 时,Σ(P[i]*Table[i] + P[i]*L[i])的最值,由Σ(M[i]*Table[i])=0可知,背包的容量为Σ(M...
阅读全文
摘要:题目链接:http://poj.org/problem?id=2353 状态方程:f[i][j]= Max{ Max{ sum[j]-sum[k-1]+f[i-1][k] | k<=j } , Max{ sum[k]-sum[j-1]+f[i-1][k] | k>j } }。复杂度O(n*m^2),如果不优化的话会TLE。分离状态转移方程: 1,k<=j 时,f[i-1][k]-sum[k-1]; 2,k>j 时,f[i-1][k]+sum[k]; 即把与j相关的分离出来,那么维护一个前缀最小和后缀最小就可以了,并且记录位置。 1 //STATUS:C++_AC_172
阅读全文
摘要:题目链接:http://poj.org/problem?id=3034 此题的状态方程很容易想出来,以时间为阶段划分,然后地图为状态,f[k][i][j]=Max{ f[k-1][x][y]+t | t=sum( map[k][p][q] && (p,q)在线段(i,j)-(x,y)上 }。 转移的时候用点小技巧就可以了,就是先把通方向上的单位整数向量求出来,在更新的时候逐个用 n*单位整数向量 (n满足距离不超过d) 来更新f[k][i][j],最后遍历一遍最值。 此题有一个很坑的trick:hammer可以在正整数坐标轴的外面,很坑啊有不有!!!足足贡献了4个WA= = 1
阅读全文
摘要:题目链接:http://poj.org/problem?id=3612 状态转移方程容易想出:f[i][j]=min{ f[i-1][j]+c*(j-k)+(j-h[i])^2 | h[i-1]<=k<=maxh && h[i]<=j<=maxh },k为上一个pole的可能高度,maxh为所有poles的最高高度。 可以算出上面的转移方程复杂度是O(n*100*100),铁定超时。仔细想下还是可以优化的。我们其中(j-h[i])^2与上一个状态无关,可以忽略。只剩下f[i-1][j]+c*(j-k)了,其f[i-1][j]是常数,而c*(j-k)是变量
阅读全文
摘要:题目链接:http://poj.org/problem?id=1947 题目要求,在一颗树上,求一个点数为n的联通分支最少需要截断的边的个数。 容易想到状态转移方程f[u][j]=Min{ f[v][k]+f[u][j-k] | 1 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include10 #include11 #include12 using namespace std;13 #define LL __int6414 #define pdi pair15 #define Max(a,b...
阅读全文
摘要:题目链接:http://poj.org/problem?id=3590 自己暴力给水过去了,不过效率有点低。题目要求的就是给一个数n,要你求出一种方案,一些和为n的数的最小公倍数最大。题目数据量不大,容易想到用暴力的办法求出所用情况,然后比较就可以了,然后再剪下枝就可以过了。不过有更好的方法。和为n的数的最大公倍数可以用DP求出来:f[i][j]表示和为i的数划分为j个循环节时的最大公倍数,则f[i][j]=max{f[i-k][j-1] | j-1<=k<i-1};然后就是求最小的置换了。设n的最大公倍数是m,则有p1^k1*p2^k2*……*pn^kn=m,显然有p1^k1+p
阅读全文
摘要:题目链接:http://poj.org/problem?id=1322 比较水的DP,只是精度有点坑。f[i][j]表示放置i次后,桌子上有j个chocolate的概率。显然,f[i][j]=sum{f[i-1][j-1]*(c-j+1)/c+f[i-1][j+1]*(j+1)/c};但是如果不优化,会超时,注意到f方程式随着i的增大是收敛的,所以当n很大时,只要计算前面就可以了,大概1000足够。我做的时候是比较精度fbs(f[i][j]-f[i][j-2])<esp,这样求出来c=100时,大概只要500次,但WA了,证明还是不足够收敛。显然这里还可以用滚动数组优化。 1 //STA
阅读全文
摘要:题目链接:http://poj.org/problem?id=3254 状态压缩,用01分别表示pasture不能plant和能plant。转移方程:f[k][i]=sum{f[k-1][j] | j是能满足i的状体,不产生冲突},显然可以用滚动数组优化。 详细的转移方法(上一个的状态设为k,i为所在行数): 1,如果前一个pasture已被plant,那么下一个pasture必定不能plant,所以f[i][k&~(1<<j)]+=f[i-1][k]; 2,如果前一个pasture没有plant: a,下一个pasture不plant,那么f[i][k]+=f[...
阅读全文
摘要:题目链接:http://poj.org/problem?id=2411 啪啦啪啦敲了80+行,1A。结果看Discuss,别人20行就解决了= =!,果然是我想复杂了。我的状态压缩效果不是很好,貌似很挫,因为状态考虑得太多了,没有类化,用了2bit的空间来表示每个格子的状态即当前放的是横向01,没放00,竖向11。而且状态转移的时候考虑的是从后面来判断前面的状态是否可行,这样的话每行就多记录了些状态(需要记录格子为空的情况)。 其实简单的做法就是从前一状态推向后一状态,用0表示当前格子放置了,1表示当前格子放置的是竖向的,而且是向下凸出的。状态转移方程:f[k][i]=sum{f[k-...
阅读全文
摘要:题目链接:http://poj.org/problem?id=1338 第i个数又前面的数的2,3,5的倍数决定,因此,记录2,3,5所在数位置,然后递推。 1 //STATUS:C++_AC_0MS_172KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #inclu
阅读全文
摘要:题目链接:http://poj.org/problem?id=1191 化简公式,然后记忆化搜索求解。a=sqrt( Σ(xi-x)^2/n ) => n*a^2=(x1-x)^2 + (x2-x)^2 + ...... + (xn-x)^2 => n*a^2=(x1^2+x2^2+......+xn^2) - 2*(x1+x2+......xn)*x + n*x^2 . 可以看出就是求分割后平方和的最小值,然后记忆化搜索就可以了,f[k][x1][y1][x2][y2]为方块(x1,y2)-(x2,y2)还需分割k次后的平方和的最小值。这里可以先求出所有方块的平方和值,使得在搜索
阅读全文
摘要:题目链接:http://poj.org/problem?id=1080 题目大意是匹配DNA分子,使得DNA可能性最大。开始自己想的是O(n^3)的算法,构造字符串,然后在状态转移,结果POJ过了,但是HDOJ WA,果然POJ的数据比较水,但是现在还没有想出问题在哪里(明天把问题找出来)。其实这个类似于LIS,基本模型:E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1]+zij}。 POJ AC/HDOJ WA代码: 1 //STATUS:C++_POJ AC/HDOJ WA_79MS_584KB 2 #include<stdio.h>
阅读全文
摘要:题目链接:http://poj.org/problem?id=2533 基本DP:f[i]=max{f[j]}+1。 1 //STATUS:C++_AC_32MS_184KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector>10
阅读全文
摘要:题目链接:http://poj.org/problem?id=1260 基本DP,只要证明最优解中不会有交叉替换,得出转移方程:f[i]=min{f[j]+(a[j+1]+..+a[i]+10)*p[i]}。由(ai+10)*bi+(aj+10)*bj=(ai+aj+10)*bj ==> (ai+10)*bi=ai*bj 替换==> t*bi=ai*bj 可证。 1 //STATUS:C++_AC_0MS_176KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #
阅读全文
摘要:题目链接:http://poj.org/problem?id=3267 题目大意是,给定一个文本串和n个模板串,要你去掉文本串中最少的字母,使得文本串能连续的被模板串匹配。有点像LIS,基本的DP模型:E[j]=opt{D+w(i,j)}。用f[i]表示前i个字符连续被模板串匹配时去掉的最少的字符个数,则f[i]=min{f[j]+(i-j+1)-max{lengthstring}},(0<=j<=i-1)。lengthstring为在i-j子串中能被匹配的模板串的长度。如果我们在没求一次i-j时就去匹配判断一次,复杂度有点高。这里显然可以优化,就是从后开始判断,然后依次记录每个模
阅读全文