摘要:
这算是八皇后问题的变种了,普通的组合数学已经很难一下子将他求出来了,除此之外,我们用纯模拟来处理该题。 给定是一个N*N的矩阵,要求在这个图中放置K个点,这些点不能够相邻(包括上下左右以及对角线上的区域),用模拟如何来过这一题呢,那就是要推出动态递归方程,F[i][s][k] 代表第i行处于第s个状态且到目前行共下了k个棋子的总方案数,c[s]代表针对s这个状态有多少个1,有动态方程:F[i][s][k] = sum{ F[i-1][s'][k-c[s]],其中 s 与 s' 为不冲突的方案数 } 该方程的含义为 F[i][s][k] 中剩余的棋子数 k-c[s] 在上一行截止 阅读全文
摘要:
题义就是在给定的图中判定是否存在欧拉回路。图G的一个回路,若它恰通过G中每条边一次,则称该回路为欧拉(Euler)回路。具有欧拉回路的图称为欧拉图(简称E图)。这里总结下各种图的判定的方法:1.无向图中:所给定的图为连通图,且所有节点的度为偶数;2.有向图中:所给定的图为连通图,且所有节点的度为零。代码如下:#include <cstdlib>#include <cstring>#include <cstdio>#define MAXN 1010using namespace std;int cnt[MAXN], set[MAXN]; int find(in 阅读全文
摘要:
图的作用图是一种表示工具,改变问题的描述方式,往往是创造性的启发式解决问题的手段.一种描述方式就好比我们站在一个位置和角度观察目标,有的东西被遮挡住了,但如果换一个位置和角度,原来隐藏着的东西就可能被发现.采用一种新的描述方式,可能会产生新思想.图论中的图提供了一种直观,清晰表达已知信息的方式.它有时就像小学数学应用题中的线段图一样,能使我们用语言描述时未显示的或不易观察到的特征、关系,直观地呈现在我们面前,帮助我们分析和思考问题,激发我们的灵感. 阅读全文
摘要:
题中定义了什么叫做可见线段。所谓可见线段就是在给定的垂直与x轴的直线中,能够在两个直线之间连接一条平行线,并且这条平行线不与任何其他的直线相交。WA一次,就是因为没有考虑到在建立点树的过程中会出现将 [1, 2] 和 [3, 4] 视为一条连接的直线,所以最后给坐标乘以一个2.代码如下:#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <vector>#include <map>#define MAXN 800 阅读全文
摘要:
http://poj.org/problem?id=3667经典线段树,不解释了。代码如下:#include <cstdlib>#include <cstring>#include <cstdio> #include <algorithm>#define MAXN 50000 using namespace std;struct{ int l, r; int lmax, rmax, max, cover;}seg[MAXN*4];void build(int f, int l, int r){ int mid = l+r >> 1; 阅读全文
摘要:
题目大意为给定一段内存快,要求根据命令输出正确的答案。New x 申请长度为x的空白内存的首地址,如果不满足输出Reject NewFree x 释放包含x节点的内存块,注意该内存块为一个New操作所确定的区域,即不必要将物理相邻的内存块视作一个内存块Get x 得到从左到右的第x个内存块Reset 重置总区间针对这些要求,设定一棵线段树,每个节点保留左,右连续空白段,以及区间总长。这样便能够处理New命令,而Free以及Get命令则用vector保留,用二分搜索优化。代码如下:View Code #include <cstdio>#include <cstring># 阅读全文
摘要:
前面还一位这是一道最长上升子序列的题目,只觉得无从下手,后来得知是最长连续上升子序列,于是有了想法。 (英文不好啊,题目中就能看出来的)对于每一个节点保留其左起及右起连续子序列长度和整个区间的最长连续长度。当然利用这三个信息加之线段树的结构我们就能够得到所要的结果。先说说我自己的写法(后来证明是写复杂了),对于每个询问我定义了三个状态 0, 1, 2。 0 表示该区间内不需要从左边或者是右边开始计算,1 表示求这段区间的右连续, 2 表示这段区间的左连续,然后就是一连串的分解判断,详见代码。该题的调试过程多亏了丽丽同学的帮助,自己生成的数据,用别人AC的代码跑结果,然后再和自己的结果比较... 阅读全文
摘要:
http://poj.org/problem?id=2533该题是最裸的LIS题,这里有两种方法。代码如下:#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int a[10000], dp[10004];int main(){ int N; while (scanf("%d", &N) == 1) { int ans = 1, m; for (int i = 0; i < N; ++i) { scanf("%d&q 阅读全文
摘要:
http://acm.hdu.edu.cn/showproblem.php?pid=3016这题是一个游戏题,名曰:是男人就下一百层。就是给定一系列的坐标,首先是纵坐标,然后是线段的左右坐标,最后是在该条线段的增加或者扣除的血量。解决这题的关键在于如何处理这多条线段的关系,如果是从上而下的话,那么我们能够更新一条边的两个端点下的最优值,那么对于后面加入的边就有下面的动态方程: sum[f] = max( sum(x), f.x1 <= x <= f.x2 ) + val(f) 需要在该边的区域内寻找最大值来更新这条边的两个端点值,这样做显然处理起来较麻烦,时间开销也比较大。所以我们 阅读全文
摘要:
Ackerman函数 Ackerman函数定义如下:A(1, 0) = 2A(0, m) = 1 m >= 0A(n, 0) = n + 2 n >= 2A(n, m) = A(A(n-1, m), m-1) n, m >= 1Ackerman函数的反函数 ackerman函数的反函数——α(x)增长极为缓慢。对于可以想象到的n,α(n)都是在5之内的用途 并查集的“路径压缩”算法:在集合的查找过程中顺便将树的深度降低。采用路径压缩后,每一次查询所用的时间复杂度为增长极为缓慢的ackerman函数的反函数——α(x)。对于可以想象到的n,α(n)都是在5之内的。 阅读全文