随笔分类 - DP
动态规划
摘要:题意:对于一个数n,如果它能被它各个数位上的除了0的数字整除,则是good number。给定区间[a, b],问good number的数量。(a, b 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 #include 17 #include 18 #include 19 #include 20 #include 21 #include 22 #include 23 #include 24 #include 25 #i...
阅读全文
摘要:题解:f(x)表示x的各个数位的数字之和,求满足x在[a, b]之间且x = 0(mod f(x))的所有x的个数。解法:数位DP,这道题思维难度一般,但是充分体现了数位DP锻炼代码的特性。 设d[i][j][k][l]表示长度为i,各位数字之和为j,除以k余l的数的个数。具体状态转移方程见代码。tag:数位DP 1 /* 2 * Author: Plumrain 3 * Created Time: 2013-12-16 12:19 4 * File Name: DP-HDU-4389.cpp 5 */ 6 #include 7 #include 8 #include 9...
阅读全文
摘要:题意: 给定区间[a,b],求将区间中所有数写在黑板上,要写的数字‘1’的次数。(1 7 #include 8 #include 9 10 using namespace std;11 12 #define CLR(x) memset(x, 0, sizeof(x))13 typedef long long int64;14 int64 d[25][20];15 int dit[25];16 17 int64 mypow(int64 p, int64 n)18 {19 int64 ret = 1;20 while (n){21 if (n & 1) r...
阅读全文
摘要:题意: 将含有连续的三个6的数称为不吉利数,比如666,1666,6662,但是6266吉利。则666为第一个不吉利数,输入整数n,求第n个不吉利数。(n 7 #include 8 #include 9 10 using namespace std; 11 12 #define CLR(x) memset(x, 0, sizeof(x)) 13 typedef long long int64; 14 int64 d1[20][10][10], d2[20][10][10]; 15 16 int64 get_num(int64 x) 17 { 18 int len ...
阅读全文
摘要:题意:对于一个数x,将其表示成十进制为(An,An-1...A2,A1),则F(x) = An*2^(n-1) + A(n-1)*2^(n-2) + ... + A2*2 + A1。给定整数a,b,求F()值不超过F(a)且属于[0,b]的整数有多少个。a,b 7 #include 8 #include 9 10 using namespace std;11 12 #define CLR1(x) memset(x, -1, sizeof(x))13 #define CLR(x) memset(x, 0, sizeof(x))14 15 int dit_b[20], d[20][10000...
阅读全文
摘要:题意:将含有连续的"49"的数称为不吉利数,每给出一个n,[1, n]中不吉利数的个数。n 7 #include 8 #include 9 10 using namespace std;11 12 #define CLR(x) memset(x, 0, sizeof(x))13 typedef long long int64;14 int64 d[25][3], dit[20];15 16 int64 gao(int64 x)17 {18 int64 len = 0, ret = 0;19 bool xxx = 0;20 CLR (dit);21 whil...
阅读全文
摘要:题意:定义一个数如果含有数字4,或者出现“62”则为不吉利数,否则为吉利数。比如242,8262均不吉利, 但22682吉利。求区间[a, b]中有多少个数为吉利数。 0 7 #include 8 #include 9 #include 10 11 using namespace std;12 13 #define CLR(x) memset(x, 0, sizeof(x))14 15 int s[20], d[10][3];16 17 int gao(int x)18 {19 int ret = x + 1;20 CLR (s);21 int len = 0...
阅读全文
摘要:题意:在一个n*m的网格上,从(0,0)走到(n-1,m-1),每次只能向右或者向下走一格。一个人最初有一个生命值x,走到每一个格生命值会变为x + s[i][j],(s[i][j]可为负,0,正),若生命值小于等于0,则人死亡。告诉网格上所有s[i][j],求x的最小值使得该人能够或者走到(n-1,m-1)。|s[i][j]| 0) d[i][j] = max(d[i][j], d[i-1][j] + s[i][j]), if (d[i][j-1] > 0) d[i][j] = max(d[i][j], d[i][j-1] + s[i][j])。初始化时将所有d[i][j]赋值为-1。
阅读全文
摘要:题意:有两种人,一种人只会说真话,另一种人只会说假话。只会说真话的人有p1个,另一种人有p2个。给出m个指令,每个指令为a b yes/no,意思是,如果为yes,a说b是只说真话的人,如果为no,a说b是只说假话的人。注意,a可以为b。保证每个指令都是正确的,且相互之间不矛盾。问,能不能确定哪些人是说真话的人,如果能,输出所有只说真话的人;如果不能,输出no。解法:首先,用并查集建树,每个节点有两个参数,f和r,f表示父亲节点的编号,r表示与父亲节点是不是同一种人。r为0表示该节点与父亲节点是一种人,r为1表示该节点与父亲节点不是一种人。则用并查集处理之后,就可以分为k棵树,每棵树上可能有x
阅读全文
摘要:题意:有一颗苹果树,每个节点上有一些苹果,任何两个节点之间的距离都为1,每走一步距离都增加1,无论该边有没有被走过。问,在最多走k步的情况下,最多能吃到多少个苹果。解法:设d[x][i][0]表示在以x为根的树上,最多走i步,并且最终回到节点x所能吃到的最多的苹果数。 设d[x][i][1]表示在以x为根的树上,最多走i步,并且最终不需要回到节点x所能吃到的最多的苹果数。注意到,一定有d[x][i][1] >= d[x][i][0]。 易得d[x][i][0] = max(d[x][i][0], d[x][i-j-2][0] + d[y][j][0]),其中y为所有x的子节点。 ...
阅读全文
摘要:题意:给一棵含有n个节点的树,问最少切割多少条边,能够得到一棵恰好包含p个节点的子树。解法:设d[x][i]表示以x为根的子树,切割出含有i个节点的子树最少需要切割多少条边。对于每个子节点y,可以直接将其切掉,也可以对以y为根的树进行切割,然后给以x为根的树增加节点数。这个地方其实就是一个背包,好好体会。 状态转移方程为d[x][i] = max(d[x][i]+1, d[x][i-j] + d[y][j])。 注意枚举的时候要逆序,否则要多开一维数组。tag:树形dp, 背包 1 /* 2 * Author: Plumrain 3 * Created Time: 2013-1...
阅读全文
摘要:题意:一只蜗牛,它的房子在树上的某个叶子节点上,它要从树的根节点出发,寻找自己的房子。树的任意两个节点的距离为1,房子出现在每个叶子节点上的可能性一样。有的节点上有虫子,如果有虫子,虫子会告诉蜗牛它的房子是不是在这个节点为根的子树上。求蜗牛所走距离的最小期望。 如下图,如果蜗牛制定的策略先到2,再到5再到4,则由于房子地点的不确定,所以可能走的距离为1,4,6,所以期望为11/3。如果制定的策略是先到3,根据虫子的话判断去4和5还是去2,则可能走的距离为2,4,3,所以期望为9/3 = 3。可以证明,最小的期望即为3。解法:首先,设叶子节点总数为tt,则肯定会有tt种情况,所以只需要求出所..
阅读全文
摘要:题意:如下图所示,给出n*m的网格,其中P表示能放炮兵,H表示不能放,每只炮兵的射程如图涂黑部分。在防止误伤的前提下(任何一个炮兵不在其他炮兵的射程内),问最多能拜访多少炮兵。(n 7 #include 8 #include 9 #include 10 11 using namespace std; 12 13 #define CLR(x) memset(x, 0, sizeof(x)) 14 #define PB push_back 15 16 int n, m, sz; 17 bool a[200][20]; 18 int d[105][70][70]; 19 vect...
阅读全文
摘要:题意:用1*2的瓷砖拼出m*n的矩形。问有多少种拼法。解法:设d[i][j]表示第i行状态为j的情况下,最多能有多少种拼法,对于状态j,1表示为竖着放置的瓷砖且它横跨i和i+1两行,其余皆用0表示。d[i][j] += d[i-1][k],其中k表示能转移到j的状态。tag:状压dp 1 /* 2 * Author: Plumrain 3 * Created Time: 2013-11-19 01:01 4 * File Name: DP-POJ-2411.cpp 5 */ 6 #include 7 #include 8 #include 9 #include 10 11 u...
阅读全文
摘要:题意:在m*n的矩阵上,1表示能放牛,0表示不能放。要求放的牛不能相邻(上下相邻或者左右相领),问放牛的方法种数。解法:设d[i][j]表示第i行状态为j的情况下,能放的牛的数量。d[i][j] += d[i-1][k],其中k表示能转移到j的状态,num(j)表示状态为j的行所放的牛的数量。当然,还要判断一下状态j是不是能放在第i行。tag:状压dp 1 /* 2 * Author: Plumrain 3 * Created Time: 2013-11-18 23:37 4 * File Name: DP-POJ-3254.cpp 5 */ 6 #include 7 #incl...
阅读全文
摘要:题意:娱乐场里面的那种打鼹鼠的游戏机。如下图。在n*n的游戏机上,每个整点都可能出现鼹鼠,鼹鼠分为m批出现。每一批鼹鼠出现的时候,如果锤子在点(i,j),则锤子可以移动到以(i,j)为圆心,d为半径的圆内任何一个整点,且移动路径(包括首尾)上的所有鼹鼠都会被打。(注意,锤子可以移动出游戏机的范围)。初始时,锤子可以在任何点,给定n,m,d和所有鼹鼠出现的时间和位置,问所有鼹鼠都出现之后,最多能打到多少鼹鼠。解法:就是一个普通的dp,设d[i][j][k]表示第i批鼹鼠出现后,锤子停留在(j,k)的情况下,能打到最多的鼹鼠数量。 状态转移方程为if(ok(j, k, x1, y1) d[i]..
阅读全文
摘要:题意:如下图所示,蜘蛛侠在某个位置,他女朋友在另一个建筑(WestTower)上,蜘蛛侠每次可以吐丝到附近的建筑顶端,然后摇摆到关于该建筑物对称的位置。只要荡到横坐标 >= X(WestTower)的位置,就能爬上WestTower。问在不碰到地的情况下,最少要吐多少次丝。解法:由于蜘蛛侠的纵坐标始终没变所以不需要记录纵坐标。对于每个建筑物,由于不能碰地所以只有一定的范围内能够吐丝到该建筑物并且移动,对每个建筑物,设这个范围为(l[i], r[i])。(l[i]和r[i]易求) 设d[j]表示到达横坐标j所需要最少次数。枚举每个建筑物i,d[j] = min(d[j-k] + 1)(l[
阅读全文
摘要:题意:如下图,有一种n*m的网格,每个格子里可能分别有两种矿物a[i][j]和b[i][j],在网格的上边和左边分别有这两种矿物的收集站。对每个网格,可以建立向上或者向左的传送带,将该格所有矿物传送。但是,传送带不能变方向,否则变方向之前的矿物会从传送带上掉落下来。比如,矿物如果从(i,j)传送到(i,j-1),再传送到(i-1,j-1),就会掉落。问最终能收集到的矿物最多为多少(两种矿物数量之和)。解法:首先,对于第(i,j)格,如果它向左传送,则应该让(i,0), (i,1)...(i,j-1)都向左传送。向上同理。 设d[i][j][0]表示第(i, j)格向左传送的情况下,矩形(0..
阅读全文
摘要:题意:在w*h(最大100*100)的棋盘上,有的格子中放有一棵树,有的没有。问s*t的小矩形,最多能含有多少棵树。解法:最直接的想法,设d[x1][y1][x2][y2]表示选择以(x1, y1)为左下角,以(x2, y2)为右上角的矩形含有多少棵树。然后就可以很容易地递推了。可是空间复杂度为O(10^8)不能被接受。 又发现d[x1][y1][x2][y2] = d[1][1][x2][y2] - d[1][1][x1-1][y2] - d[1][1][x2][y1-1] + d[1][1][x1-1][y1-1],所以只需要预处理出所有的d[1][1][i][j]即可,然后每次求出一..
阅读全文
摘要:题意:给定一个完全由小写字母组成的字符串s,对每个字母比如x(或a,b,c...z),在字符串中添加或者删除它分别需要花费c1['x']和c2['x']的代价,问将给定字符串变成回文串所需要的最少代价为多少。解法:设d[i][j]表示将字符串中从第i位至第j位变成回文串所需要的代价。若s[i] == s[j],d[i][j] = d[i+1][j-1];否则的话,有四种处理方法。 对xa.......by,可以将其变为xa......b,yxa.....by,a.......by,xa.....byx中的任意一种再处理。所以d[i][j] = min(d[i][
阅读全文

浙公网安备 33010602011771号