- 博客(88)
- 收藏
- 关注
原创 poj1463树形动归
给定一棵树,怎样使得占据最少的节点能够监视所有的边 Sample Input 4 0:(1) 1 1:(2) 2 3 2:(0) 3:(0) 5 3:(3) 1 4 2 1:(1) 0 2:(0) 0:(0) 4:(0) Sample Output 1 2 思路分析:(树形DP) 1.最优子结构: 所求问题是根部覆盖或者不覆盖所得到的最优解,那么子问题为其儿子覆
2017-03-24 10:36:58
557
原创 求最大子列和 dp
求最大子列和:动态规划 定状态: b[j]:前j个数的最大子列和 状态转移方程: b[j] = max{b[j-1]+a[j],a[j]}, 1 b[j]表示1~j序列的最大子列和 #include #include #define N 1000005 using namespace std; int n; int a[N]; int maxsum() { int sum =
2017-03-23 20:32:24
369
原创 最长上升子序列LIS
LIS: dp[i]含义:以下标为i的元素为结尾的最长上升子序列的长度 dp[]初始化为1 dp[i] = max(dp[j]+1){其中0 最后结果为max{dp[i],0 #include #include #include #define N 1005 using namespace std; int a[N]; int dp[N]; int n; int main(
2017-03-23 20:20:24
380
原创 最长公共子序列LCS
考虑最长公共子序列问题如何分解成子问题,设A=“a0,a1,…,am-1”,B=“b0,b1,…,bm-1”, 并Z=“z0,z1,…,zk-1”为它们的最长公共子序列。不难证明有以下性质: (1) 如果am-1=bn-1,则zk-1=am-1=bn-1,且“z0,z1,…,zk-2”是“a0,a1,…,am-2” 和“b0,b1,…,bn-2”的一个最长公共子序列; (2) 如果am-1
2017-03-23 20:17:20
345
原创 poj1163数字三角形
给定已知三角形,求从顶部走出底部路径权值和的最大值,权值均在0~99且为整数。三角形行数不超过100。 每次只能向左下或右下方走 Sample Input 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 Sample Output 30 思路: 动归方程:dp[i][j] = max(dp[i+1][j],dp[i+1,j+1]) + map[i
2017-03-23 20:13:03
384
原创 poj1384完全背包恰好装满
#include #include #include #define N 10050 using namespace std; const int inf = 0x3f3f3f3f; int n, v;//物品的种数,背包的容量 int dp[N], c[N], w[N]; void init()//恰好装满的初始化 { for (int i = 1; i <= v; i++) d
2017-03-23 20:09:40
767
原创 完全背包
完全背包问题:已知有n中物品和一个容量为v的背包,每种物品均有无限件,第i种物品的费用为c[i],价值是w[i] 求如何放使得物品费用总和不超过背包容量,且价值总和最大。 方法1: 仿照01背包,对每件物品的取件数再穷举,即确定每件物品的件数范围,然后当做01背包处理。 f[i][j] = max{f[i-1][v-k*c[i]] + k*w[i]} 0 方法2:(优化)
2017-03-23 20:07:20
271
原创 01背包问题
01背包问题 有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。 求解将哪些物品装入背包可使价值总和最大。 特点是:每种物品仅有一件,可以选择放或不放。 f[i][v] = Max{f[i−1][v], f[i−1][v−c[i]] + w[i]} 时间复杂度O(n*v),空间复杂度O(n*v) 空间复杂度可优化为O(n),可采用滚动数组。
2017-03-23 20:03:09
312
原创 硬币游戏
Alice和Bob发明了一种新的两人游戏。最初,地面放置有一摞共n个硬币( 5 输入: 单组用例。 第一行有正整数n (5 之后n行,每行一个整数,第i + 1行的整数代表Ci( 1 Ci <= 100000 ) 输出: 一行,一个整数代表
2017-03-23 19:52:07
1554
原创 矩阵连乘的动态规划算法
矩阵链乘问题 输入: 共两行 第一行 N ( 1 第二行有 N+1 个数,分别为 A1 、 A2 ...... An+1 ( 1 输出: 共两行 第一行 M ,为最优代价。注:测试用例中 M 值保证小于 2^31 第二行为最优顺序。如 (A1((A2A3)A4)) ,最外层也加括号。 注意:测试用例已经保证了输出结果唯一,所以没有AAA的情况. inpu
2017-03-23 19:44:58
1799
原创 主定理
主定理 d n=2 T(n) = aT(n/c)+bn^x n>2 θ(n^x) a T(n) = θ(n^x*logn) a=n^x θ(n^logc(a)) a>n^x
2017-03-13 22:32:07
578
原创 汉诺塔问题
#include using namespace std; void Hano(int n, char src, char mid, char aim)//把n个盘子从src通过mid移动到aim中 { if(n==1) { cout " << aim << endl; return; } Hano(n-1,src,aim,mid); cout " << aim <<end
2017-03-13 22:29:28
265
原创 百练:爬楼梯
树老师爬楼梯,每次可以爬一阶或者两阶,共有n阶楼梯,问有多少走法。 爬n阶台阶可以分为:1.先爬一阶台阶,再爬n-1阶台阶。2.先爬两阶台阶,再爬n-2阶台阶。 最后得出递归表达式 f(n) = f(n-1)+g(n-2); #include #define N 100005 using namespace std; int f(int x) { if(x==1||x==2) r
2017-03-13 22:28:56
375
原创 百练:算24
描述 给出4个小于10个正整数,你可以使用加减乘除4种运算以及括号把这4个数连接起来得到一个表达式。 现在的问题是,是否存在一种方式使得得到的表达式的结果等于24。 这里加减乘除以及括号的运算结果和运算的优先级跟我们平常的定义一致(这里的除法定义是实数除法)。 比如,对于5,5,5,1,我们知道5 * (5 – 1 / 5) = 24,因此可以得到24。又比如,对于1,1,4,2, 我们
2017-03-13 22:28:30
443
原创 百练:放苹果
把m个相同的苹果放在n个相同的盘子里,允许有的盘子空着不放, 问共有多少种不同的放法?5,1,1和1,5,1是同一种放法 #include using namespace std; int f(int m, int n) { if(m<n) return f(m,m); if(m==0) return 1; if(n==0) return 0; else return f(m,
2017-03-13 22:27:43
261
原创 求主元素
求主元素:先求出中位数,由于主元素必为中位数,因此只需要判断中位数出现次数是否大于n/2即可。 寻找中位数:用线性方法寻找第k大的数即可在O(n)内找到中位数。 设T[0:n-1]是n个元素的数组。对任一元素x,设S(x)={ i | T[i]=x}。当|S(x)|>n/2时,称x为主元素。设计一个线性时间算法,确定T[0:n-1]是否有一个主元素。 #include #inclu
2017-03-13 22:25:09
511
原创 线性时间寻找一列无序数中第k大的数
线性时间寻找一列无序数中第k大的数 分治思想 #include #include #include #include #define N 100005 using namespace std; int partition(int a[], int s, int e) { int m = (s + e) / 2; int i = s, j = e; int pivot = a[s
2017-03-13 22:24:22
593
原创 求一列数前m大的数
思想: 一.先排序,在输出后m个元素。(复杂度O(nlogn)) 二.先把前m大的元素弄到数组最右边,在对这m个数进行排序(复杂度为O(n+mlogm),其中 把前m大的元素弄到数组最右边花费为O(n)) 如何把前m大的元素弄到数组最右边? 1.以a[0]为枢轴,把比他大的放在其后,比它小的放在其前。记录它比他大的元素个数(包括自己)为cnt 若cnt==m,函数结束 cnt
2017-03-13 22:22:21
744
原创 求逆序对个数(分治)
求逆序对个数 在归并排序(从大到小)的合并过程前,对两个分支进行逆序对数的计算(该计算过程为O(n)) #include #include #include #define N 100005 using namespace std; int a[N], b[N]; void Merge(int a[], int s, int m, int e, int tmp[]) { int p
2017-03-13 22:21:34
2550
原创 递归:求波兰表达式
波兰表达式的定义: 1.一个数是波兰表达式,其结果就是该数的值 2.“运算符 波兰表达式 波兰表达式”,也是波兰表达式,其值为两个波兰表达式的值的计算结果 #include #include #include #define N 20 using namespace std; double exp()//读入一个逆波兰表达式,返回其结果 { char s[N]; cin >> s
2017-03-13 22:20:41
1435
原创 百练:简单整数划分
整数划分问题是算法中的一个经典命题之一,有关这个问题的讲述在讲解到递归时基本都将涉及。 所谓整数划分,是指把一个正整数n写成如下形式: n = m1 + m2 + ... + mi; (其中mi为正整数,并且1 <= mi <= n),则{ m1,m2,...,mi }为n的一个划分。 如果{ m1,m2,...,mi }中的最大值不超过m,即max(m1, m2, ..., mi) <= m,则
2017-03-13 22:19:54
286
原创 百练:2的幂次方表示
#include #include #include using namespace std; void f(int n) { if (n == 1) { cout << "2(0)"; return; } if (n == 2) { cout << "2"; return; } int num = 1, cnt = 0; while (num <= n)
2017-03-13 22:16:26
554
原创 N皇后问题
以下为只输出结果的代码 include #include #define N 10 using namespace std; int vis[3][2*N];//分别标记列,主对角线,副对角线。注意对角线可能有2*n-1个,数组要开大点。 int n; int cnt = 0; void dfs(int cur)//cur表示当前行,i*i方阵 { if (cur > n)//已放满
2017-03-13 22:15:38
199
原创 归并排序实现及时间复杂度分析
归并排序思想: 1.把序列分为两部分,对两部分分别排序(拆分的边界条件:元素大于1个) 2.合并已排序两部分 时间复杂度分析: T(1) = 1; T(n) = 2*T(n/2) + a*n;(a为常数,每次合并时,复杂度为O(n)) = 2*(2*T(n/4)+a*n/2) + a*n = 4*T(n/4) + 2*a*n = 4*(2*T(n/8)+a*n
2017-03-13 22:13:11
795
原创 快速排序实现以及时间复杂度分析
快速排序思想: 1.选择数组左边第一个元素为枢轴pivot,把数组所有元素比pivot大的放在数组右边,比pivot小的放在左边 (复杂度为O(n)) 2.对pivot左右两边的序列分别进行快速排序。 平均时间复杂度分析: T(1) = 1; T(n) = 2*T(n/2) + a*n;(a为常数,每次合并时,复杂度为O(n)) = 2*(2*T(n/4)+a*n/2) + a*
2017-03-13 22:11:57
3578
原创 hdu1233还是畅通工程
某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离。省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小。请计算最小的公路总长度。 Input 测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 当N为0时,输入结束,该用例不被处理。 Output 对每个测试用例,
2017-02-25 16:54:27
186
原创 hdu1863畅通工程
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连, 只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。 现请你编写程序,计算出全省畅通需要的最低成本。 Input 测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( 行对应村庄间道路的成本,每行给出一对正整数,分别
2017-02-25 16:48:09
316
原创 hdu1875畅通工程再续
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要 通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题, 政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后, 决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。 当然,为了节省资金,只要
2017-02-25 16:42:02
862
原创 hdu1879继续畅通工程
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连, 只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用, 以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。 Input 测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1 对应村庄间道路的成本及修建状态,每行给4个正
2017-02-25 15:28:08
285
原创 poj1287最小生成树水
已知有n个点,m条边,求最小生成树。 Sample Input 1 0 2 3 1 2 37 2 1 17 1 2 68 3 7 1 2 19 2 3 11 3 1 7 1 3 5 2 3 89 3 1 91 1 2 32 5 7 1 2 5 2 3 7 2 4 8 4 5 11 3 5 10 1 5 6 4 2 12 0 Sample Output
2017-02-25 14:52:46
272
原创 poj1231最大连续子序列和并输出子列的位置
Problem Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和 为20。 在今年的数据结构考卷中,要求编写程序得到最大和,现在增加一个要求,即还需要输出该
2017-02-23 16:14:37
977
原创 并查集总结
并查集模板 void init()//初始化 { for (int i = 1; i f[i] = i; } int find(int x)//路径压缩,寻根 { return x == f[x] ? x : f[x] = find(f[x]); } void merge(int x, int y)//合并两个元素所在集合 { int t1 = find(x),
2017-02-18 16:33:12
319
原创 poj1988 带权并查集
带权并查集的应用 题意: 说是有n块砖,编号从1到n,有两种操作,第一是把含有x编号的那一堆砖放到含有编号y的那一堆砖的上面 ,第二是查询编号为x的砖的下面有多少块砖。 思路:带权并查集,用dis[i]表示元素i下边有多少个元素,num[i]表示元素i所在堆的砖块总数 或者说 dis[i]:当前元素到树根的距离 num[i]:当前元素所在树的大小(即树中元素个数) Sample In
2017-02-18 16:29:42
225
原创 poj1838 并查集 抽象模型
题意: 一个点用坐标(x,y)表示,如果两个点在水平方向或垂直方向上相邻,则两个点属于一个区域, 即点1(x1,y1),点2(x2,y2)相邻当且仅当x1==x2,|y1-y2|=1或者|x1-x2|=1,y1=y2。 给定一些点,相邻的点构成一个区域,求出k个区域所能拥有的最大点数(k不大于区域数) Input 第一行两个整数n和k分别代表点数和区域数,之后n行为n个点的坐标 Out
2017-02-18 14:08:57
396
原创 poj2236并查集简单应用
并查集的基本应用 题目:输入电脑个数n,(电脑标号为1到n)相邻电脑交流的最大距离d。输入n台电脑的坐标。 起初n台电脑均被破坏。两台电脑之间可通过第三台电脑相互交流。 下边有两种输入: O i。修复第i台电脑 S a b 判断电脑a和b是否能交流,若能输出SUCCESS,否则输出FAIL。 思路: 用并查集处理。 输入遇到O:标记当前电脑已修复,找出已修复的其他所有电脑看是否能合
2017-02-18 14:04:54
304
原创 poj2492种类并查集
种类并查集的应用 题意:有n只bug,下边给出m对关系,每对关系都表示他们能相互交配,判断其中是否有同性恋。 思路:典型种类并查集,一共有两类:男女。对于每只bug,创建两个元素:i-A,i-B。并用2*n个元素的并查集 维护。 1.i-x表示i属于种类x 2.并查集里到达每一个组表示组内所有元素代表的情况都同时发生或者不发生 输入的u,v如果是同一性别(下边维护的两种情况,因此此处
2017-02-18 14:03:44
346
原创 poj1703 种类并查集
种类并查集的应用 定义并查集为: 并查集里的元素i-x表示i属于帮派x 同一个并查集的元素同时成立 可见所有元素个数为2 * N,如果i表示属于帮派A,那么i + N表示属于帮派B, 每次输入两个家伙不在同一帮派的时候,就合并他们分属两个帮派的元素。 输入量比较大,要用scanf,用cin会超时 #include #define N 100005 int f[2 * N]; in
2017-02-18 14:02:31
257
原创 poj1611并查集求元素所在集合的元素总数
并查集应用:求某元素所在集合的元素个数 题目:已知有n个人,m个团队,已知0号选手有病毒,病毒会传染给他所在任一小组中的人。 求最后有病毒的人的个数。 思路1:对相同团队的人进行合并,最后输出与0在同一集合的元素个数。 即是否满足find(0)==find(i)。 思路2:对相同团队的人进行合并,合并过程中对集合元素个数num也和并,最后找到0的祖先的num即可 思路1: #incl
2017-02-18 13:59:43
599
原创 poj1308 判断是否为树
题目:已知有m条边连接顶点,判断其是否为一棵树 思路:树的条件: 要么是空树,要么满足连通无环 1.无环(可通过并查集判断) 2.连通(不能出现森林,即所有输入的点必须只在一个集合里边) 自己wa了好几遍。 总结下来有几个原因: 1.空树特判 2.输入问题,无论是不是树,都必须输入完数据才行。 3.初始化一定要放在最前边 4.连通无环是并列关系,但是只要一个不满足,在输入完成的
2017-02-18 13:54:51
468
原创 poj1182食物链 种类并查集
种类并查集 1.定义:rank为0代表父节点与子节点是同一物种,rank为1代表父节点吃子节点,rank为2代表子节点吃父节点。 这个定义与输入的type相符合,type-1==1表示x吃y,type-1==0表示同一物种 2.路径压缩:儿子对爷爷的关系==(儿子对父亲的关系+父亲对爷爷的关系)%3。可通过穷举法证明。 3.集合合并:以左为尊处理f【】数组,rank数组的值根据两次使用路径
2017-02-18 13:51:17
360
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人