随笔分类 -  ACM/算法

摘要:由于动态开辟内存会引致超时,所有需要预先申请一大片内存。字典树详解请见上一篇博文。View Code 1 #include <iostream> 2 #include <cstring> 3 #define branchNum 11 4 using namespace std; 5 6 int k;//记录使用了的Tnode 7 8 struct Trie_node 9 {10 Trie_node *next[branchNum];11 bool isStr;12 }Tnode[100050];13 14 class Trie15 {16 private:17 T... 阅读全文
posted @ 2012-03-10 13:36 Veegin 阅读(211) 评论(0) 推荐(0)
摘要:文章作者:yx_th000文章来源:Cherish_yimi (http://www.cnblogs.com/cherish_yimi/) 转载请注明,谢谢合作。关键词:trie trie树 数据结构前几天学习了并查集和trie树,这里总结一下trie。 本文讨论一棵最简单的trie树,基于英文26个字母组成的字符串,讨论插入字符串、判断前缀是否存在、查找字符串等基本操作;至于trie树的删除单个节点实在是少见,故在此不做详解。lTrie原理Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。lTrie性质好多人说trie的根节点不包含任何字符信息,我 阅读全文
posted @ 2012-03-10 13:25 Veegin 阅读(607) 评论(0) 推荐(0)
摘要:与背包算法一样,这算法也是一个非对称算法。这里不写证明之类的定理推论了,需要的话网上可以搜到到很多,书本例如算法导论也有详细的证明。简写一下算法的步骤:•(1)选择两个大素数P、Q ,其中P!=Q(这里使用 Miller_Rabin近似算法 确定素数)(2)计算N=P*Q (3)选择一个小奇数作为公钥(加密密钥)E,使其与(P-1)*(Q-1)互质(使用 扩展欧几里德算法 求出)(4)选择私钥(解密密钥)D,满足如下条件: (D*E) mod (P-1)(Q-1)=1(使用 扩展欧几里德Extend_Euclid(E,(P-1)*(Q-1))=1,求E的逆元,即为D)(5)加密时,明文PT计算 阅读全文
posted @ 2011-08-11 19:13 Veegin 阅读(2564) 评论(0) 推荐(0)
摘要:这是一个非对称算法,即可生成多个不同的公钥,分发给其他人,然后其他人用各自的公钥加密文件,而算法只生成一个私钥(自己保存),这私钥可解密不同公钥加密的文件。在不知道私钥的前提下,破解文件是一个NP难问题。下面贴上高老师的讲义:1.背包算法基于背包问题的简化版,即子集和问题(Subset sum)。2.子集和问题:给定一个整数集A(俗称为背包)和整数b,要求找出A的一个子集,使得其中元素之和等于b。3.子集和问题是NP完全问题。然而若集合A是一个超级增长序列(Superincreasing),则可以使用简单的贪婪策略在多项式时间求解。4.超级增长序列指集合中后一个元素大于前面所有元素之和。如 { 阅读全文
posted @ 2011-08-08 10:22 Veegin 阅读(5577) 评论(0) 推荐(1)
摘要:在刚接触这道题的时候,确实无从下手,因为我记得高老师说过01背包算法并不是一个好算法,时间复杂度是指数级。这题容量为实数时,更是无法直接解决。参考了一下别人的思路,发现原来可以把银行总存款作为背包容量,把被抓率转换成逃脱率(即1-被抓率)作为背包物件的价值,进行动态01决策。求出比最低逃脱率大的第一个逃脱率,这时的偷得的存款即为最大可偷的存款。代码如下://以总资产为容量,以逃脱率为价值,DP求出第一个比最低逃脱率大的最大偷钱数目#include <stdio.h>#define M 100050#define N 150double C[M],r[N];//r[N]为逃脱率,w[ 阅读全文
posted @ 2011-08-02 21:03 Veegin 阅读(540) 评论(0) 推荐(0)
摘要:集训期间学会了动态规划的01背包,想去刷几道水题看看代码有没有问题,没想到遇到POJ3624,我原来的二维背包因为数据太大而不能AC,然后我到网上查看一下别人的方法,才看见,背包问题可以用一维!仔细想一下,对啊,这道题,用一维数组更新其值就可以了。于是重写代码,AC。代码如下:#include <stdio.h>#include <string.h>#define N 3500#define M 13000int d[N],w[N],val[M],n,W;void knapsack(){ int i,j; memset(val,0,sizeof(val)); for(i 阅读全文
posted @ 2011-08-01 17:34 Veegin 阅读(2455) 评论(0) 推荐(0)
摘要:看了几天关于最大流的书,今天找一道最经典的最大流题目hdoj1532,跟poj1273一样的题目,起初WA了,不知道什么原因。后来在POJ的discuss看到,原来是重边的问题,对该细节疏忽了。然后把代码改了一下,AC。这里用的是增广路算法——Edmons-Karp。算法思想是,从零流(所有边的流量均为0)开始不断增加流量,保持每次增加流量后都满足容量限制、斜对称性和流量平衡3个条件。这个算法基于这样的一个事实:残量网络中任何一条从s到t的有向道路都对应一条原图中的增广路——只要求出该道路中所有残量的最小值d,把对应的所有边上的流量增加d即可,这个过程称为增广。不难验证,如果增广前的流量满足3 阅读全文
posted @ 2011-05-05 19:52 Veegin 阅读(1598) 评论(5) 推荐(0)
摘要:素数打表:void oddp(){ int i,j; for(i=0;i<1000000;i++) a[i]=1; a[0]=0; a[1]=0; for(i=2;i<1000000;i++) { if(a[i]==1) { for(j=i*2;j<1000000;j+=i) a[j]=0; } }}结合POJ2262代码:int main(){ int num; int i,flag; oddp(); while(scanf("%d",&num)!=EOF&&num!=0) { for(flag=0,i=2;i<num;i+ 阅读全文
posted @ 2011-04-29 09:59 Veegin 阅读(1731) 评论(1) 推荐(0)
摘要:Silver Cow PartyTime Limit:2000MSMemory Limit:65536KTotal Submissions:5052Accepted:2151DescriptionOne cow from each ofNfarms (1 ≤N≤ 1000) conveniently numbered 1..Nis going to attend the big cow party to be held at farm #X(1 ≤X≤N). A total ofM(1 ≤M≤ 100,000) unidirectional (one-way roads connects pa 阅读全文
posted @ 2011-04-29 09:46 Veegin 阅读(428) 评论(0) 推荐(0)
摘要:从廉政师兄和志权师兄那里学会了最短路径的Dijkstra,Floyd,Bellman-Ford算法和最大匹配算法。思考完模板后,终于找了一道水题POJ1502先来练练Dijkstra算法。 Dijkstra给我的第一感觉跟Prim有点相似。只是更新权值的方式不同,因为要求的是最短路径,所以每个点的消耗都是累计之前相连的点的消耗。以下是小弟POJ1502的代码:#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 120#define MaxInt 0x3f3f3f3fint n,m 阅读全文
posted @ 2011-04-29 09:44 Veegin 阅读(1560) 评论(0) 推荐(0)
摘要:今天刚掌握Kruskal算法,写下随笔。对于稀疏图来说,用Kruskal写最小生成树效率更好,加上并查集,可对其进行优化。Kruskal算法的步骤:1.对所有边进行从小到大的排序。2.每次选一条边(最小的边),如果如果形成环,就不加入(u,v)中,否则加入。那么加入的(u,v)一定是最佳的。并查集:我们可以把每个连通分量看成一个集合,该集合包含了连通分量的所有点。而具体的连通方式无关紧要,好比集合中的元素没有先后顺序之分,只有“属于”与“不属于”的区别。图的所有连通分量可以用若干个不相交集合来表示。而并查集的精妙之处在于用数来表示集合。如果把x的父结点保存在p[x]中(如果没有父亲,p[x]= 阅读全文
posted @ 2011-04-29 09:37 Veegin 阅读(12513) 评论(3) 推荐(3)
摘要:今天从志权师兄那里学会了最小生成树。所谓生成树,就是n个点之间连成n-1条边的图形。而最小生成树,就是权值(两点间直线的值)之和的最小值。首先,要用二维数组记录点和权值。如上图所示无向图:int map[7][7]; map[1][2]=map[2][1]=4; map[1][3]=map[3][1]=2; ......然后再求最小生成树。具体方法是:1.先选取一个点作起始点,然后选择它邻近的权值最小的点(如果有多个与其相连的相同最小权值的点,随便选取一个)。如1作为起点。visited[1]=1;pos=1;//用low[]数组不断刷新最小权值,low[i](0<i<=点数)的值 阅读全文
posted @ 2011-04-29 08:42 Veegin 阅读(87387) 评论(19) 推荐(10)