随笔分类 - 题解
题解
摘要:这题第一问就是最长上升序列,不解释。 第二问说一下,首先,如果i可以打到j,那就把i,j之间加一条边,然后搜最大匹配。最大匹配出来的结果是边数的结果,然后用节点数减去变数就是有多少条链(画图看),感觉好像生物里的氨基酸——多肽。 代码:#include <stdio.h>#include <string.h>#include <stdlib.h>#define max(a, b) ((a)>(b)?(a):(b))struct num{ int x, y, z;}num[1000];int f[1000];int ans, n;int map[1000
阅读全文
摘要:转的题解:最长公共上升子序列(LCIS)的平方算法预备知识:动态规划的基本思想,LCS,LIS。问题:字符串a,字符串b,求a和b的LCIS(最长公共上升子序列)。首先我们可以看到,这个问题具有相当多的重叠子问题。于是我们想到用DP搞。DP的首要任务是什么?定义状态。1定义状态F[i][j]表示以a串的前i个字符b串的前j个字符且以b[j]为结尾构成的LCIS的长度。为什么是这个而不是其他的状态定义?最重要的原因是我只会这个,还有一个原因是我知道这个定义能搞到平方的算法。而我这只会这个的原因是,这个状态定义实在是太好用了。这一点我后面再说。我们来考察一下这个这个状态。思考这个状态能转移到哪些状
阅读全文
摘要:这题好难,我不写题解了,直接转发吧:KMP算法大家应该烂熟于心才好,这样碰到这样的题才能灵活运用。有时做题真的需要一点灵感。首先,这个题如果想要求出从每个位置开始的字串的匹配长度,那么O(n^2)以内的算法应该是很难的。但是,这个题要求的并不是“每个位置的长度”,而是“具有这样长度的位置数”。因而,灵活使用KMP算法自我匹配的性质,就能够解决这个问题。考虑下面的例子:A串:abbabbabababbababbaB串:abbabababba应用KMP算法,很容易得到B串的自我匹配是元素 a b b a b a b a b b a位置 1 2 3 4 5 6 7 8 9 10 11长度 0 0 .
阅读全文
摘要:这个题目有点价值吧,设f[i]为i的不同组合有多少种,那么i就可以表示成(i - 1) + 1,也就是i - 1有多少种排列i就有多少种,但是比如i=6的时候,可以表示成2+2+2, 4+2,这里没有出现1,怎么办呢?可以看到i为偶数的时候一定可以把i表示成2*(i / 2)。 然么就可以得到: f[i]=f[i - 1], i 为奇数时 f[i]=f[i - 1] + f[i / 2], i为偶数时,又题目说9位数,所以要求模。 代码:#include <stdio.h>#include <stdlib.h>int f[10000001];int main(int a
阅读全文
摘要:简单DP,设f[i][j]是取i个数,左边取j个,转移方程: f[i][j] = max(f[i - 1][j - 1] + i * num[j], f[i - 1][j] + i * num[n - (i - 1 - j)]);2011年7月16日 08:55:21添加: 昨晚删数那题,又看了下这题,就觉得这题不能用区间动态规划吗?仔细对比了一下,还真不能,这里的i无法用区间动态规划里的什么来表示,所以这里不能用区间动态规划。 代码如下:#include <stdio.h>#include <stdlib.h>int num[2001];int f[2001][200
阅读全文
摘要:DFS,枚举,结构上我没加什么优化,很明显有,因为上下可以对称,左右可以对称,对角线也可以对称,但是太复杂了,难得写,就没去优化。 就是对角线上的枚举可能有点让人看不懂吧,我觉得自己画个图,把每个坐标写好,然后看对角线的坐标之间的共同特点就知道该怎么枚举了,代码:#include <stdio.h>#include <stdlib.h>int num[100];int max_[100][101], min_[100][101];int sum[100][101];#define min(a, b) ((a)<(b)?(a):(b))#define max(a,
阅读全文
摘要:题目一直没看懂,最近终于看懂了题目,不怎么难,就是DP,和石子合并一模一样,不细说了(打工好累,想睡了。) 代码:#include <stdio.h>#include <stdlib.h>int num[100];int max_[100][101], min_[100][101];int sum[100][101];#define min(a, b) ((a)<(b)?(a):(b))#define max(a, b) ((a)>(b)?(a):(b))int rpn = 0xFFFFFFF, rpx;int main(int argc, char **a
阅读全文
摘要:直接DFS,没太多说的,比较简单的题目:#include <math.h>#include <stdio.h>#include <stdlib.h>int num[10];int put[10];int used[10];unsigned ans;int n, k;int ok(int a, int b){ if(abs(num[a] - num[b]) <= k){ return 1; } return 0;}void srch(int now){ int i; if(now == n){ //最后还要判断一下now - 1是否和1满足这个条件 if
阅读全文
摘要:挺好的一个题目,第一次做博弈类型的题目,希望TYVJ里还有更多的这类题目给我做,f[i][j]代表上一次对手取了j个,自己还有i个可取的时候能取的最大值,方程如下: f[i][j] = max(sum[i]-f[i-k][k]) (1<=k<=2*j),然后可以看到f[i][j - 1]会把1<=k<=2*(j-1)计算一次,而f[i][j]又要计算一次,重复了。所以……可以修改成: f[i][j] = max(f[i][j - 1], f[i - 2 * j][2 * j], f[i - (2 * j - 1)][2 * j - 1]); 把这段话记录一下:首先明确这
阅读全文
摘要:这题的模式需要记住一下,当需要从上下同时得到最优的时候,我记得还有一题NOIP的原题也是这个类型的,题目。。合唱队形也是类似的,两个DP相加。 这题还是有一点学习和参考的价值,代码:#include <stdio.h>#include <stdlib.h>int f1[27][27], f2[27][27], num[26][26];#define max(a, b) ((a)>(b)?(a):(b))int main(int argc, char **argv){ int n; int i, j; scanf("%d", &n); f
阅读全文
摘要:一定要经过n / 2, n / 2,就是说从上面到n / 2这一行都只能取最右边的一个,然后下面的部分DP就行了。 代码:#include <stdio.h>#include <stdlib.h>int num[25][25];int f[26][25];#define max(i, j) ((i)>(j)?(i):(j))int main(int argc, char **argv){ int i, j; int n, ans = 0; scanf("%d", &n); for(i = 0; i < n; i++){ for(j
阅读全文
摘要:....太水了...排序,输出, Ok.#include <stdio.h>#include <string.h>#include <stdlib.h>char name[10000][100];int num[10000];int com(const void *a, const void *b){ return *(int *)a - *(int *)b;}int com_(const void *a, const void *b){ return strcmp(a, b);}int main(int argc, char **argv){ int i;
阅读全文
摘要:说是说一颗星啊,但是空间要考虑啊,这种图的结构是我第二次写,上一次我也不记得是什么时候了,反正是看到别人的代码写的,觉得这种结构挺好的!!线性存放整个图,使用起来也方便,就是不大好理解,我也不打算解释(个人很懒,语文成绩也不好,说不清楚。毕竟只是报告嘛,没打算太给别人看,呵呵。懒。。)。 代码:#include <stdio.h>#include <assert.h>#include <stdlib.h>int head[100000];int next[200000];int edge[200000];int end;void add(int a, int
阅读全文
摘要:怎么讲。。纯水题吧,随便搜一下就可以了。 不过搜法也有很多,我第一次写的是直接求距离,因为要开平方,又是O(n^2)的复杂度,所以没超时。但是最后一个数据293ms,有点危险,看了下题解,有好方法,直接使用x^2+y^2,不开平方,毕竟就是比较距离嘛! 写出来的那个代码全部WA了,不知道怎么回事,好困了,明天继续写。——2011年7月6日 22:53:12 也不知道怎么回事,重写一次就直接AC。 有点无语的说,上代码:#include <stdio.h>#include <stdlib.h>struct dot{ int x, y;}dot[2000];double g
阅读全文
摘要:USACO原题,做过几次了,所以一次AC,就是暴搜,因为数据小。 先把每个牧区的直径求出来,然后再把在一个牧区中距离任意节点的最远距离算出来,然后暴搜,若i,j之间加一条路,那么新牧区的半径要么就是i所在的牧区的的直径,要么是j所在的牧区的直径,要么就是i所在的牧区中距i最远的距离加上j所在的牧区中距j最远的距离加上i,j之间的距离。 看代码最有效:#include <math.h>#include <stdio.h>#include <stdlib.h>#define INF 100000000struct dot{ int x, y;}dot[150];
阅读全文
摘要:刚接手真的好难,因为是MOD100啊,本来可能很大了,结果MOD一下就变成0了,一个很小的值就是最佳答案了。 对此,解决方法是用f[a][b][i]来代表第a行第b列能否产生出值为i的路径,如果能则为1,不能则为0。网上有一个人给它取名我挺喜欢,叫做布尔染色。然后方程就是f[a][b][i] = max(f[a + 1][b + 1][(100 + i - num[a][b]) % 100] +f[a + 1][b][(100 + i - num[a][b]) % 100]),我代码的DP和这个不一样,因为代码比理论感觉简单一点,不废话了,上代码: Ps: 最近比较喜欢用函数来写DP,然后用.
阅读全文
摘要:真的好悲催,不知道是手生了还是蠢了,查了好久发现问题出在宏上面把变量名写错了。 这题比较简单吧,就是一个模拟,或者说BFS,广搜。。代码:#include <stdio.h>#include <assert.h>#include <stdlib.h>#define MAX 50000char map[150][151];struct { int x, y;}queue[MAX];int start, end;int cost[150][150];int used[150][150];void enqueue(int a, int b){ int t = (e
阅读全文
摘要:DP,最近做TYVJ感觉挺有效果的,比较难得先跳过,前期先练手感,把手感练好了,再慢慢提升难度。 题目比较简单,调试了好一阵,提交了几次,羞愧。。代码:#include <stdio.h>#include <stdlib.h>unsigned num[30], f[30][30];int p[30][30];unsigned ans(int s, int t){ int i; unsigned a = 0, b; if(s == t){ return num[s]; } if(s > t){ return 1; } if(f[s][t]){ return f[s]
阅读全文
摘要:呼,写死我了,最开始写的DP,没太仔细想,结果!!超时,超得真过瘾啊!呵呵,后来知道该用贪心,就是相当于一个”赫夫曼树“,当然,我没用那算法,也不记得那算法了,用的堆,不过也好久没写了,提交至少5次,最后发现主要的问题是出在一个寻找父节点的那个宏上。手生了,联系了一下堆。#include <stdio.h>#include <stdlib.h>int heap[10001];int len, ans;#define left(i) (((i) << 1) + 1)#define right(i) (((i) << 1) + 2)//把parent
阅读全文
摘要:这题一开始确实会感觉很难,但是罗马数字的个位只有可能是{"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"},同理,十位上的数字也永远都是固定的,所以还是简单吧,实现代码如下:#include <stdio.h>#include <stdlib.h>char num[4][10][5] = { {"", "
阅读全文
浙公网安备 33010602011771号