经典
文章平均质量分 75
logic_nut
这个作者很懒,什么都没留下…
展开
-
pku 2186 Popular Cows(强连通分量)
强连通分量的一种求法:先深搜整个网络中的每个节点,记录每个节点访问结束的顺序(如代码中过的DFS1函数)。反转图中边的方向。按节点访问结束从后往前的顺序,深搜,每一棵深搜形成的树就是一个强连通分量(如代码中的DFS2函数)。 下面说明部分转自http://www.cppblog.com/RyanWang/archive/2009/02/26/74984.aspx,同时也参原创 2009-08-28 10:37:00 · 1170 阅读 · 1 评论 -
pku 1836 Alignment(最长递增子序列)
最长递增子序列的应用。从前往后跑一遍,然后从后往前跑一遍。最后枚举。#include #include template void Get_Max(T& a,T b){ if(a<b) a=b;}using namespace std;double height[1005],temp_height;double min_height[1005];int cnt[10原创 2009-09-09 21:07:00 · 713 阅读 · 0 评论 -
google code jam 2008 Mousetrap (逆向)
题目大意:After reading the story, it is not hard to see that the task is clear: put card 1 in the first position, then for each card i (in the order 2, 3, ..., K), we start from the current position, and原创 2009-09-10 11:47:00 · 759 阅读 · 0 评论 -
google code jam 2008 Milkshakes(贪心)
google的题目每道都很经典,看似是NP-HARD问题,却能够贪心解决。官方分析:On the surface, this problem appears to require solving the classic problem "Satisfiability," the canonical example of an NP-complete problem. The custome原创 2009-09-09 18:07:00 · 1506 阅读 · 2 评论 -
zju 1013 Great Equipment(DP)
先DP缩小范围,后枚举。 题目大意:背包问题变种。有三种物品,分别对应有weight,size,vlaue,有n个背包,每个背包也有对应的可容纳weight和可容纳size。用所有的背包,在weight和size的限制下,能得到三种物品的数量x,y,z,ans=max(x*vx+y*vy+z*vz)+extra,这里有一个比较特殊的地方在于三种物品按某一数量组合,可以得到“套装”,会有额外原创 2009-07-12 01:25:00 · 909 阅读 · 1 评论 -
google code jam PermRLE(最短哈密顿通路)
字符串压缩,转换成求哈密顿通路。问题ProblemYouve invented a slight modification of the run-length encoding (RLE) compression algorithm, called PermRLE.To compress a string, this algorithm chooses some permutat原创 2009-09-17 17:42:00 · 1393 阅读 · 0 评论 -
pku 1191 棋盘分割(DP,一点点数学)
那个式子可以化简,其实是求xi的最小平方和。DP来做。中间因为个很愚蠢的错误送了n次WA。#include #include #define _clr(a,b) memset(a,b,sizeof(a))template void get_min(T& a,T b){ if(a>b) a=b;}using namespace std;int sum[9][9];原创 2009-09-22 21:49:00 · 749 阅读 · 0 评论 -
pku 1077 eight(据说有人用8中搜索算法做了这道题目)
状态有9!种,用的全排列的hash。首先写了个A*算法,0ms过了,但内存消耗挺大。其他方法的代码会陆续添加。好久没写过这种2500B+的代码。 A*#include #include #include #define _clr(a,b) memset(a,b,sizeof(a))using namespace std;const int maxn=3628原创 2009-09-20 17:11:00 · 875 阅读 · 0 评论 -
pku 1635 Subway tree systems(树的同构,最小表示)
树的同构的判断,先用深搜得到以某个节点为起点的01表示,0表示往远离中心的节点走,1表示往靠近中心的节点走。用了两种方法做。1.把树去除根节点后,可以分成数棵子树。每个子树对应一个01串,然后用字符的比较函数排列这些01串。递归调用,得到树的一种最小表示。下面的代码因为反复使用string,速度很慢很慢。#include #include #include #inclu原创 2009-09-21 09:34:00 · 1517 阅读 · 3 评论 -
google code jam 2008 Number Sets(模拟,数论)
google的题目总是看上去很直白,但却藏有很多优化方式。给个官方的分析。The process described is fairly slow: Create singleton sets of integers. Take each pair of integers; factor the two integers and see if they have a原创 2009-09-09 10:41:00 · 619 阅读 · 0 评论 -
pku 3267 The Cow Lexicon(很经典的字符串DP)
这个题的最大特点是待匹配的串中有杂音。如果把字典做成hash存储,采用枚举杂音点的方法来匹配,效率是O(L*2^L),这是没办法接受的。这样的问题我们一般要逆着来,把字典往待匹配的字符串里面代,效率可以做到O(L*W*25)。总之,很经典很经典。#include "string.h"#include "math.h"#include #include #include原创 2009-09-09 11:02:00 · 742 阅读 · 0 评论 -
pku 1724 ROADS(搜索,记录状态)
用DFS,BFS始终过不了,一直TLE,后来不得已上了priority_queue。方法有点类似dijkstra,节点比较的时候先比dist,dist相同的时候选择money小的。这种方法有一个好处是可以在priority_queue.top.position==end的时候直接结束,纯BFS,DFS则需要等到队列为空才能确定最后的答案。用一个数组dist_s[i][j]=k记录状态,表示原创 2009-09-01 17:16:00 · 760 阅读 · 0 评论 -
pku 3352 Road Construction(割边,缩点)
无向图求割边:以任一节点为起点,深搜,记录每个节点第一次访问的时间DFn,同时记录当前节点不经过其父节点能够访问DFn值最小的节点low。假设a是b的父亲,如果low[b]题目:给定一个网络,求最少增加多少条边,可以使这个网络成为一个稳定的网络(网络中任意一个节点坏掉,整个网络仍然保持连通)。算法:找到割边,获得双连通分量。将同一双连通分量内的节点缩成一个节点,则整个网络变成了一棵树。通过原创 2009-08-28 19:31:00 · 834 阅读 · 2 评论 -
pku 3308 Paratroopers(带权二分图最小点覆盖)
把伞兵看成边,行列看成节点,转化为了带权二分图最小点覆盖。加入超级源点和超级汇点,源点和所有行节点相连,所有列节点和汇点相连,如果a行b列有敌人,则把节点a和节点b相连。则问题又可以转化求最小割。现在求源点和汇点之间的最小割。因为对任一敌人,必然有source-->a-->b-->sink, 割的性质是"不存在一条从source到sink的路径", 故路径上的三条边, , 中至少有一条边在原创 2009-08-29 13:42:00 · 1741 阅读 · 1 评论 -
pku 2528 Mayor's posters(线段树)
很典型的线段树,区域比较大需要加离散化。之前做pku3277,离散化后没有排除重合的点也过了。今天照着上次那样写过不了,想了几种情况后发现之前的做法是错误的,对于这种统计区域内颜色的问题离散化后必须排除重合点。上次可以过是因为那是求的面积才没有影响。看到discuss里有人说 离散化+倒着贴,想想的确不失为一个好办法。#include #include using namespac原创 2009-08-29 16:59:00 · 805 阅读 · 0 评论 -
pku 2828 Buy Tickets(线段树)
倒着往队列里面插,每插入一个位置,就说明这个位置已经有人占了,删除这个位置。比如说数据 pos value,那么就寻找队列中除去已经有人占据的位置后的第pos+1个位置。 我的代码是用标准规格的线段树写的,节点有left,right,cnt(记录该区段内被占据的位置的数量)域。看到有些别人的代码,直接只用节点记录该区段内剩余有效位置数量,把insert和search操作结合,是个很原创 2009-08-30 10:28:00 · 1803 阅读 · 1 评论 -
pku 3411 Paid Roads(搜索,卡节点访问数量)
题意:http://acm.pku.edu.cn/JudgeOnline/problem?id=3411寻找最短路径,但这个最短路径和通常意义上的不太一样,因为可以预付款,因此可能为了便宜的预付款而绕道而行。每个节点可能访问多次,每条边也可能访问多次。我的做法是DFS,卡节点访问数量。因为多绕一次道是为了增加至少一个预付款的节点,因此当一个节点的访问数量已经是N(我觉得应该是N-1,但那样原创 2009-09-01 09:58:00 · 963 阅读 · 2 评论 -
pku 3264 Balanced Lineup(RMQ)
首先依次给定一条线段上每个点的高度。然后执行查询操作,要求输出在范围[i,j]内最高点和最低点的高度之差。 这是一个很典型的RMQ问题,关于这个问题有个很出名的DP解答方式。ST(动态规划) O(nlogn)-O(1) offline通过O(nlogn)的预计算,可以达到O(1)的查询。 关于这个算法,在百度百科里面摘抄一点:ST算法(Sparse Table),以求最原创 2009-08-30 14:22:00 · 636 阅读 · 0 评论 -
pku 3368 Frequent values(转换,RMQ)
题目:首先给定一个非降序的数列,然后进行查询操作,问范围[l,r]内出现频率最高的数字出现了多少次。个人很喜欢这道题目,因为通过巧妙的转换,能使它成为一个RMQ问题。a[i]是原数列,b[i]是转换后的数列。b[i]代表与a[i]相同的左边的节点数(包括自己),例如,(-1 -1 1 1 1 1 3 10 10 10)==>(1 2 1 2 3 4 1 1 2 3)。这时候因为一个数字原创 2009-08-30 16:42:00 · 652 阅读 · 0 评论 -
pku 1961 Period(KMP扩展)
给定一个字符串,问它的前2位是否是周期字符串,前3位。。。前n位?数据量大,要线性求解一个字符串才行。这题可以直接利用KMP算法求得的next数列来判断。next[i]=j,表示str[0..j]=str[i-j..i],因为是一个串,所以串的前str[0..i-j-1]是相同的,利用辗转相等可以发现,当(i+1)%(i-next[j])==0即可得到该串为周期串。 之前虽然想到了利用原创 2009-08-31 16:56:00 · 915 阅读 · 1 评论 -
pku 2481 Cows(预处理,树状数组)
给定n个区间(l,r),问每个区间被多少个另外的区间所包含。包含的定义(l1,r1),(l2,r2),如果l1 用节点存储区间,然后给节点排序。l小的区间放在前面,l相同则r大的区间放在前面。为什么这样排序呢?因为对排序之后的节点,节点n只可能被排在它前面的(0--n-1)号节点包含,而不可能被后面的包含。那么(0--n-1)号节点中,又哪些能包含节点n呢?只要ri>=rn即可原创 2009-09-21 18:29:00 · 962 阅读 · 3 评论 -
google code jam Star Wars(判断多元不等式是否有解)
题目只需要输出最小的power,不需要求解坐标。直接用二分查找,枚举所有坐标点看是否满足。 找到满足(|xi - x| + |yi - y| + |zi - z|) ≤ piY的最小的Y。Ahyangyi的代码充分利用了该式的对称性 x + y + z ≤ xi + yi + zi + piY x + y + z ≥ xi + yi + zi - piY x + y - z原创 2009-09-19 11:46:00 · 1241 阅读 · 1 评论 -
pku 1740 A New Stone Game(博弈,感性)
博弈类问题的关键,就是寻找平衡状态。这题的平衡状态是什么?石头堆的数量是成对出现的,也就是说后取者总可以模仿先取者。逐一分析:剩余1堆石头:先取者全部拿走,胜利。剩余2堆石头:假设两堆石头的数量相等,均为m。对于(m,m),先取者没办法一次将两堆石头拿走,则后取者总可以模仿先取者的动作,只需换一下操作对象,使两堆石头变成(n,n)。最后肯定有某一次先取者操作后石头只剩下一堆,这原创 2009-10-22 08:20:00 · 1309 阅读 · 1 评论 -
pku 2425 A Chess Game(SG函数)
额,没什么可讲的,要讲我也讲不清楚,大家还是去看SG函数吧。#include #include using namespace std;vector edges[1000];int N,M,GS[1000],ans;int DFS(int n){ if(GS[n]!=-1) return GS[n]; bool used[1000]; memset(use原创 2009-10-22 08:29:00 · 706 阅读 · 0 评论 -
pku 1966 Cable TV Network(求无向图的点连通度)
求无向图的点连通度。解决办法:拆点,转换为求边连通度。通常情况下怎么求边连通度?给每条边赋权值1,任意选择源点,枚举汇点,依次求最小割。那么求无向图的点连通度该怎么建图?拆点,对于原始无向图中的边(a,b),在新图中有(a+N,b)=(b+N,a)=INF。同时对i任意选择起点,枚举汇点,求(start+N,end)的最大流,即最小割。需要注意的是,当最小割的值大于等于N,原创 2009-10-29 20:34:00 · 1348 阅读 · 0 评论 -
pku 1948 Triangular Pastures(背包)
首先一个想法是,尽量凑出三条长度差不多的边,然后计算面积。但是这样不对,我们并不能保证那就是最优解。后来依照海伦公式写了个式子,看有没有极值什么之类的,未果。最终觉得,还是枚举比较合适。枚举第一条边的长度,我们需要快速知道第二条边和第三条边的取值的可能的组合。因为如果知道第二条边的长度,我们可以根据周长求到第三条边的长度,所以问题就变成了已知一条边,如何快速求另外一条边长度可能的取原创 2009-12-05 11:44:00 · 942 阅读 · 0 评论 -
pku 1944 Fiber Communications(枚举+贪心)
如果去掉最后一个顶点可以和第一个顶点相连这个条件,那么该怎么解?O(P)的贪心就可以了。因为答案必定是无环的,那么枚举断点,然后采用贪心,就可以得到O(np)的解法。#include #include #include #include #include #include #include #define PI 3.1415926535897932384原创 2009-12-04 22:52:00 · 1130 阅读 · 1 评论 -
Big Root
国内做题,从来没有用过JAVA。介于北美题对时间卡得没那么紧,而java对大数的操作比较方便,所以练习了一下。题目的意思是,给定exp和bigNum,问是否存在answer,answer的exp次方是bigNum。其中bigNum的范围是1到10^100。有了java的B原创 2011-08-22 13:07:09 · 771 阅读 · 0 评论 -
pku 1325(二分匹配模版)
最小点覆盖---最大二分匹配。题目中有个容易被忽视的地方,两台机器的初始状态都是mode 0。而处理的方法也是很有意思,就是直接忽略那些和左右0节点相连的边。#includeusing namespace std;bool map[105][105];bool vi原创 2011-09-26 01:27:19 · 567 阅读 · 0 评论 -
pku 1273 Drainage Ditches( Edmond-Karp最大流模板)
经过证明,若每次用最短的增广路径进行增广,则最多只需要O(VE)次增广。(如何证明?)用BFS求最短增广路径,每次增广复杂度是O(E)。因此,总时间复杂度为O(VE2)。该算法名叫Edmond-Karp算法。#include using namespace std;#define MAXN 205#define INF 2110000000#define MIN(x,y) (x原创 2009-08-03 12:12:00 · 1446 阅读 · 0 评论 -
pku 1082 Calendar Game (博弈,有点复杂)
思想还比较简单,根据必胜态和必负态的关系从后往前推。因为是日历,实际处理起来稍微有点复杂,不过也还好就是。如果一个节点的所有后续节点都是必胜态,该节点为必败态,否则该节点为必胜态。也即是说,只要有一个后续节点是必败态,该节点就是必胜态。最后一天为必败态,倒数第一天为必胜态,从后往前推。#include using namespace std;bool state[2005][1原创 2009-10-22 08:24:00 · 1047 阅读 · 0 评论 -
pku 2348 Euclid's Game(博弈)
这题的解法实在是精妙。对于任意一个局面(a,b),它是必胜局还是必败局这是确定的。但按这题的要求,如果要我们自己来判断却会极其难。对于局面(m,n)(m>n),两人一直往下取,必然会到局面(m%n,n)。如果m/n如果m/n>2,则局面(m,n)的先取者就可以决定由谁去面对局面(m%n,n),因为这个先取者足够聪明可以判断(m%n,n)是必胜还是必败,因此我们也已经可以确定(m,n原创 2009-10-21 07:51:00 · 1155 阅读 · 0 评论 -
pku 2976 Dropping tests(数值的二分测试)
数值的二分测试,这种方法已经在google 的比赛中见ACRUSH用了好几次了,但事实上自己一直没领会到其中的精髓,这道题目又是可以利用这种方法做解答的,真的很巧妙,很奇妙。给个官方的解答:/*Drop----This problem was intended to be the hardest problem in the set, and indeed, nobodysolved it原创 2009-10-19 16:21:00 · 881 阅读 · 1 评论 -
pku 3321 Apple Tree(时间戳,树状数组)
题目:给定一棵树(题目中默认节点1为根),树的节点上可能有苹果,也可能没有。需要查询某个节点及其子节点上的苹果数量之和,并且支持节点上长苹果或苹果被摘。分析:需要统计范围和,树状数组是个不错的选择。可是根据当前节点的编号,是没办法使用树状数组的。对于节点i,我们必须让节点i的所有子节点的编号和i连续。对此我们需要做一些预处理。建好树,用DFS对树进行后序遍历,根据访问时间给节点重编原创 2009-09-22 11:20:00 · 1143 阅读 · 0 评论 -
pku 1915 Knight Moves(双向BFS)
一直听到大家在说双向BFS,自己从来没用,于是今天也找了个题目写着玩。直接写的,没有参照别人代码。候选结点,用了两个队列保存。至于已经到达的状态,一个数组足矣。从起点出发到达的用正数表示,从终点出发到达的用负数表示。然后当整数碰到负数,说明找到了,结束。#include #include using namespace std;int n;int move[8][2原创 2009-09-20 20:16:00 · 883 阅读 · 0 评论 -
pku 1195 Mobile phones(二维树状数组)
极其标准的二维树状数组#include using namespace std;const int maxn=1050;int tree[maxn][maxn];int n;inline int lowbit(int x){ return x&(x^(x-1));}void insert(int x,int y,int t){ while(x<=n)原创 2009-09-22 12:15:00 · 495 阅读 · 0 评论 -
pku 1947 Rebuilding Roads(树形DP)
第一次写树形DP,写个总结。为什么会有树形DP?每个节点的状态的值只跟他的子节点有关,兄弟节点之间是互不影响的。应该怎么来计算树形DP?深搜,先把子节点处理好,再来对当前节点进行DP。 对于pku1947这道题目,DP[i][j]表示以i为根节点、节点数为j的子树需要去除的边的最小数量,状态转移方程有DP[root][p]=DP[root.son][k]+DP[root][p-k]原创 2009-09-24 09:51:00 · 1215 阅读 · 1 评论 -
pku 3140 Contestants Division(树的划分)
题目:给定一棵树,每个节点有一个权值。任意去掉一条边会形成两颗子树,每颗子树有一个权值和,求二者相差的最小值。分析:先求出所有节点权值总和,然后以任意一个节点为根节点,深搜,求每个节点的(本身及其子节点)权值和,直接和sum比较就可以得到去除该节点和父节点之间的边时的答案。教训:又一次栽倒在vector上,因为是多数据,每次使用vector之前都需要clear。因为忘了这个WA了数次。原创 2009-09-25 23:15:00 · 931 阅读 · 0 评论 -
pku 2486 Apple Tree(树形DP,双重DP)
题目:给定一棵树,每个节点上有一个权值,从节点1出发,可以移动k步,要使经过的节点的权值和最大。分析:dp[i][j]表示从节点i出发,可以移动j步,不需要回到起点的情况;dp_back[i][j]表示从节点i出发,可以移动j步,需要回到起点的情况。首先可以确定最外层是树形DP,而里面则是一个背包的组合问题。解答:输入中给定了节点见的邻接关系,但并未制定父子关系,根据节点1是树的根,先进行原创 2009-09-25 18:45:00 · 1050 阅读 · 0 评论 -
PKU 1821 Fence(原来DP也是会超时的。。)
O(N*N*K)的DP算法还是比较容易想到的。但可以运用一个贪心策略把O(N*N)变成O(N)。这一点还是比较难的。。。 给个抄来的解题报告 题目意思就是说给你一段墙,有K个粉刷工,每个粉刷工站在一个位置,且每个粉刷工只能刷L连续长度的墙,且要包括他所在的位置,而且每个粉刷工刷一个单位的墙的价格也不一样,问怎么刷能达到最大价钱先以P为关键字对工人进行排序,使这个顺序作为动态原创 2009-10-12 11:56:00 · 1406 阅读 · 0 评论