随笔分类 -  题解

题解
摘要:这题总算是弄好了,大致思路还是简单,我不贴思路了,贴另一个收获,如下,看下面两段代码:#include <stdio.h>#include <stdlib.h>int map[300][300];int count[300];int time[300];int ans, tot;int n, p;void maketree(int k){ int i; int j, l; for(i = 0; i < count[k]; i++){ j = map[k][i]; for(l = 0; l < count[j]; l++){ if(map[j][l] == k 阅读全文
posted @ 2011-07-25 21:02 zqynux 阅读(1004) 评论(0) 推荐(0)
摘要:本题就是数学题,比较繁琐的是误差和特殊情况。假设一个球i,它掉落到车顶的时间为t1,掉落到地上的时间为t2,则如果掉落到车顶时车的后排已经经过该点,或掉落到地上时车的前排还没有到达该点,则该点不会被接受。于是有:i<=s+l-vt1,i>=s-vt2综合考虑1e-5的误差,我们得出i的区间:[s-vt2-e,s+l-vt1+e]∩[0,n-1],而接受的球数就是该区间内的整数个数。 代码如下(其实我觉得这个代码有不好的地方,但是能AC。。数据不强大。。):#include <math.h>#include <stdio.h>#include <stdl 阅读全文
posted @ 2011-07-25 10:31 zqynux 阅读(815) 评论(0) 推荐(1)
摘要:好题!非常好的贪心题,引用别人的题解吧: 开始容易想到在所有的牌中找到最多的一堆,然后向小的牌堆上移动,一直到所有的牌都相等,但关键是不知道往哪个方向上移动才能达到移动次数最少。 设a[i]为第i堆纸牌的张数(0<=i<=n),ave为均分后每堆纸牌的张数,ans为最小移到次数。 我们按照由左而右的顺序移动纸牌。若第i堆纸牌的张数a[i]超出平均值,则移动一次(ans+1),将超出部分留给下一堆,既第i+1堆纸牌的张数增加a[i]-ave;若第i堆纸牌的张数a[i]少于平均值,则移动一次(ans+1),由下一堆补充不足部分,既第i+1堆纸牌的张数减少ave-a[i]; 问题是,在从 阅读全文
posted @ 2011-07-24 20:33 zqynux 阅读(480) 评论(0) 推荐(0)
摘要:用列队,按顺序一个个发送信号,然后当一个节点所有信号都接受了c>0就加入列队,然后继续。。。。 网上题解应该比较多,我直接上代码吧:#include <stdio.h>#include <assert.h>#include <stdlib.h>#define QMAX 1000int dot[200];int map[200][200];int link[200][200];int count[200];int queue[QMAX];int rear, head;int in[200], out[200];void enqueue(int k){ i 阅读全文
posted @ 2011-07-21 22:49 zqynux 阅读(870) 评论(0) 推荐(0)
摘要:这题和USACO里一题挺像的,具体那题是啥不记得了,反正暴力枚举就行,数据不大,代码如下:#include <stdio.h>#include <string.h>#include <stdlib.h>#define INF 0xFFFFFFF#define min(a, b) ((a)<(b)?(a):(b))int f[101];char str[101];char sub[100][101];int main(int argc, char **argv){ int i, j, k; int n, l; scanf("%s\n" 阅读全文
posted @ 2011-07-21 16:31 zqynux 阅读(165) 评论(0) 推荐(0)
摘要:直接使用了系统的排序,感觉有点作弊的感觉。。。代码:#include <stdio.h>#include <string.h>#include <stdlib.h>char str[10000][257];int com(const void *a, const void *b){ return strcmp(a, b);}int main(int argc, char **argv){ int i; int n; scanf("%d\n", &n); for(i = 0; i < n; i++){ scanf(" 阅读全文
posted @ 2011-07-21 16:18 zqynux 阅读(219) 评论(0) 推荐(0)
摘要:N比较小,暴力搜就行,代码如下:#include <stdio.h>#include <stdlib.h>int num[20];int ans = 0xFFFFFFF, n, m;int t;void srch(int now){ if(now == n){ if(t >= m && t < ans){ ans = t; } if(t == m){ printf("0\n"); exit(0); } return; } srch(now + 1); t += num[now]; srch(now + 1); t -= n 阅读全文
posted @ 2011-07-21 16:13 zqynux 阅读(211) 评论(0) 推荐(0)
摘要:贪心,转题解:很好的一道贪心。首先一个需要明确的问题就是因为要分成1*1的格子,所以每一条边肯定都要切,只不过是切的次数的多少有所不同。对于每一条纵边来说,它所需要切得次数等于在这条纵向边切之前的已经切的横边的次数。对于横边就看纵边。这样,一个很显然的想法就是让代价大的先切,这样的话满足代价大的切得次数少。把横边和纵边排个序,然后不断的维护ans即可。 代码:#include <stdio.h>#include <stdlib.h>int heng[2000], shu[2000];int ans;int com(const void *a, const void *b 阅读全文
posted @ 2011-07-21 11:54 zqynux 阅读(319) 评论(0) 推荐(0)
摘要:好题!第一,不好理解,考验!第二,锻炼了我使用C的负数坐下标的能力。 题目是个DP,f[i][j]代表以j开头的,长度为i的等差序列的数目,最后要输出的时f[i][j](-1000<=i<=1000, 0 <= j < n)(我用的C, 所以j是[0, n)。) 转移方程是:f[num[i] - num[j]][i] = f[num[i] - num[j]][i] + f[num[i] - num[j]][j] + {1}如果num[i] - num[j]不等于0就加一,代码如下:#include <stdio.h>#include <stdlib.h 阅读全文
posted @ 2011-07-19 23:36 zqynux 阅读(318) 评论(0) 推荐(0)
摘要:超猥琐的题目,该怎么说,用a做01背包的体积,b做价值,然后pascal有一个很好的机制,可以使用负数做下标,但是C没有,于是乎就像到了指针,具体实现机制看代码吧,然后就是还有一个,初始状态f[0]=0,f[i] = -∞,然后要维护DP的界,代码如下:#include <stdio.h>#include <stdlib.h>int a[100], b[100];int f_[200001];int (*f);int ans;int main(int argc, char **argv){ int n; int i, j; int max = 0, min = 0; s 阅读全文
posted @ 2011-07-18 13:39 zqynux 阅读(307) 评论(0) 推荐(0)
摘要:啊啊啊啊,越来越没用了,这么简单的题不知道提交了多少次。!~~ 直接模拟就是,不好维护的是最大高度,因为高度的范围是(0, maxin),但是这个maxint是pascal的,是32767,所以果断用used[i]保存高度为i的有多少人。 代码:#include <stdio.h>#include <stdlib.h>#define MAX 500000int used[32768];int queue[MAX];int head, rear;int count;int max;void enqueue(int k){ count++; used[k]++; queue 阅读全文
posted @ 2011-07-18 10:08 zqynux 阅读(179) 评论(0) 推荐(0)
摘要:我越来越2了,这么假简单的题目竟然能想到DP去,啊啊啊怎么办啊,,上代码:#include <stdio.h>#include <stdlib.h>int num[20000];int start;int com(const void *a, const void *b){ return *(int *)b - *(int *)a;}int main(int argc, char **argv){ int i; int n, a = 0, b; scanf("%d%d", &n, &b); for(i = 0; i < n; i 阅读全文
posted @ 2011-07-17 22:16 zqynux 阅读(210) 评论(0) 推荐(0)
摘要:怎么说这个题目,反正纯判断就可以了,不太废话,上代码:#include <stdio.h>#include <string.h>#include <stdlib.h>int num[9][9];int used[9];int corner(int a, int b){ int i, j; for(i = 0; i < 3; i++){ for(j = 0; j < 3; j++){ if(used[num[a + i][b + j]]){ return 0; } used[num[a + i][b + j]] = 1; } } return 1; 阅读全文
posted @ 2011-07-17 21:57 zqynux 阅读(284) 评论(0) 推荐(0)
摘要:自我批评一下,如此简单的题我竟乱七八糟想了一通,批评批评,太废材了,这题就01背包,不说算了,代码:#include <stdio.h>#include <stdlib.h>int f[10001];int main(int argc, char **argv){ int i, j; int n, m; int a; scanf("%d%d", &n, &m); f[0] = 1; for(i = 0; i < n; i++){ scanf("%d", &a); for(j = m; j >= 阅读全文
posted @ 2011-07-16 16:46 zqynux 阅读(274) 评论(0) 推荐(0)
摘要:f[i]表示第i天获得的最大的美元,要是浮点类型(double),f[i] = max{f[i - 1], f[j] * num[i] / num[j]}, 0 <= j < i, f[0] = 100,1<= i < n 代码如下:#include <stdio.h>#include <stdlib.h>#define max(a, b) ((a)>(b)?(a):(b))double f[100];int num[100];int main(int argc, char **argv){ int i, j; int n; scanf(& 阅读全文
posted @ 2011-07-16 16:38 zqynux 阅读(250) 评论(0) 推荐(0)
摘要:看了网上的一个人的代码,那个人是对分母循环,然后确定分子,然后搜最优解。但是他找分子的时候是考虑了一些范围的,想一下可以直接去掉这层考虑,等下说明,然后它用了gcd(最大公约数),我这里也把它去掉了,不过其实都不保险,因为吧,等下分析下: 利用的是j/i≈sqrt(p),可以写成j≈i*sqrt(p),然后i从1到n枚举,求j,然后判断j/i,这就是思路。 首先是要比sqrt(p)小的啊,i*sqrt(p)是分子,但是i*sqrt(p)是分数,而我们需要的是整数,那该怎么办,搜两个,一个是(int)(i*sqrt(p)),另一个是(int)(i*sqrt(p)) - 1,证明如下: i*sq. 阅读全文
posted @ 2011-07-16 15:32 zqynux 阅读(288) 评论(0) 推荐(0)
摘要:就是贪心,但是这个题目很猥琐,需要考虑打不过对方的情况,代码如下:#include <stdio.h>#include <stdlib.h>int a[100000], b[100000];int com(const void *a, const void *b){ return *(int *)a - *(int *)b;}int main(int argc, char **argv){ int i, j, ans = 0; int m, n; scanf("%d%d", &n, &m); for(i = 0; i < n; 阅读全文
posted @ 2011-07-16 11:47 zqynux 阅读(180) 评论(0) 推荐(0)
摘要:我不写结题报告吧,贴别人的,还是抱怨一下,题目没说清楚,说"且第i种箱子不能放在高度超过A_i的地方。"是箱顶不能超过而不是箱底不能超过,怪不得我的那个不能AC:先按照A_i 排序,最好用快速排序然后再按01背包枚举关键代码:===========================================qsort(1,n);f[0]:=true;for i:=1 to n do for j:=1 to c[i] do for k:=a[i] downto h[i] do if f[k-h[i]] then f[k]:=true;============================. 阅读全文
posted @ 2011-07-15 18:27 zqynux 阅读(195) 评论(0) 推荐(0)
摘要:刚开始还以为和那个硬币游戏一样,要用那种DP,然后我想破脑袋想不出来,后来看了题解才知道就是区间动态规划,那就简单了,方程我不写了,我的还有条件,麻烦得很,看代码里面吧。 对比了一下硬币游戏和这题,小感悟:如果是两人或多人的博弈游戏,那状态里就要有上回对方是怎么取舍的;但是如果只是自己去,那就是区间动态规划。 代码:#include <stdio.h>#include <stdlib.h>#define max(a, b) ((a)>(b)?(a):(b))int num[100];int f[101][101];//f[i][j] 表示从i到j最大取得数int 阅读全文
posted @ 2011-07-15 16:58 zqynux 阅读(258) 评论(0) 推荐(0)
摘要:刚把这题昨晚,顺便就用最大匹配把这题做了,不给思路了,直接上代码:#include <stdio.h>#include <string.h>#include <stdlib.h>int num[20];int f[20];int ans = 1;int from[20], used[20];int map[20][20];int n;int find(int k){ int i; for(i = 0; i < n; i++){ if(map[k][i] && !used[i]){ used[i] = 1; if(from[i] == - 阅读全文
posted @ 2011-07-15 15:28 zqynux 阅读(289) 评论(0) 推荐(0)