分类: 算法

  • USACO 3.1.6 Stamps 解题报告

    这一题我就用的动态规划:f[l]=max(f[l], f[l – num[i]]); f[0] = 1; l是总面额,i是第num[i]个邮票的面值,但是超时,没想到别的算法,怎么办?找地方剪枝,见了三处就AC了,这效果立竿见影啊!后来到网上看了下,还有更快的方法,我是三重循环,它是二重循环,用f来记录当前使用的邮票总数(这种方法到别出去吧~- –)

  • USACO 3.1.5 Contact 解题报告

    这个题目其实算法还是比较简单,关键是怎么保存这些数字,其实啊,最好的保存方法就是二进制,且增加前缀1,比如0就是二进制10即十进制2,想必聪明的你要问为什么需要前缀1了,为什么呢?如果不要的话那么0和00都是二进制的0,怎么区分呢?所以用前缀1,那么最大的话也就是12位的1加一个前缀1,2^13=8192,接下来自己想想吧。

  • USACO 3.1.4 Shaping Regions 解题报告

    这个题目用数组来记录纸的每一个颜色是不可能的,无论是时间上还是空间上都无法忍受,就只能用具体的矩形来表示了,比如底纸,就是一张(0, 0, a, b, 1)的底纸,代表起始坐标是(0, 0)末坐标是(a, b)颜色是1,将它加入数组作为第一个元素,当添加进了一个新的矩形的时候,将数组所有的元素都和这个新的矩形比较,如果该元素被盖住了,就把数组中的那个元素拆分成几个没有被盖住的元素。 其实描述的很笼统,代码明天加入吧,在Ubuntu里面,现在不想切换过去了。 代码如下: de lang="c">/ ID: yylogoo1 PROG: rect1 LANG: C / #include struct paper{ int x1, y1; int x2, y2; int c; }; struct paper pa[4001]; int len; int stack[4000]; int top; int pop(void) { if(top == 0){ return len++; } return stack[–top]; } void push(int k) { stack[top++] = k; } void add(struct paper t) { int k; k = pop(); pa[k] = t; } void del(int k) { pa[k].x1 = -1; push(k); } void deal(struct paper new, int old_n) { struct paper old = pa[old_n], t; if(new.x1 <= old.x2 || old.x1 <= new.x2){ return ; } if(new.y1 <= old.y2 || old.y1 <= new.y2){ return ; } del(old_n); if(new.x1 = old.x2 && new.y2 <= old.y2){ return ; } if(old.x1 new.x2){ t = old; t.x1 = new.x2; add(t); old.x2 = new.x2; } if(old.y2 < new.y2){ t = old; t.y1 = new.y2; add(t); old.y2 = new.y2; } } int color[2501]; int main(void) { int n; int i, j; int a, b; struct paper t; freopen("rect1.in", "r", stdin); freopen("rect1.out", "w", stdout); scanf("%d%d%d", &a, &b, &n); add((struct paper){0, 0, a, b, 1}); for(i = 0; i = 0){ color[pa[i].c] += (pa[i].x2 – pa[i].x1) * (pa[i].y2 – pa[i].y1); } } for(i = 1; i <2500 i ifcolori> 0){ printf("%d %d\n", i, color[i]); } } return 0; }de>

  • USACO 3.1.3 Humble Numbers 解题报告

    这个题目属于什么算法呢?我才疏学浅不知道,反正就是用num来记录丑数,假设1为丑数,代码实现会简单些,那么丑数必定就等于另外一个丑数乘以一个素数,那么再一个个的按大小找到前n个丑数,就可以了。 时间的话大概是O(nm),对每个素数都记录该和哪个丑数相乘start[i],如果sub[i](第i个素数)num[start[i]]是下一个丑数,那么start[i]就加一,如果sub[i]num[start[i]]和当前最大的丑数(就是才成为丑数的丑数)相等的话那start[i]也是要加一的,就这样循环。 / LANG: C ID: yylogoo1 PROG: humble / #include unsigned sub[100], num[100000]; int start[100]; int len; void add(int k) { num[len++] = k; } int main(void) { int i, j, k; int m, n; int min, in; freopen("humble.in", "r", stdin); freopen("humble.out", "w", stdout); scanf("%d%d", &m, &n); for(i = 0; i <m i scanfu subi add whilelen="n){" min="0xFFFFFFFF;" fori="0;" i m i ifsubi numstarti="= num[len" - starti ifmin> sub[i] num[start[i]]){ in = i; min = sub[i] * num[start[i]]; } } add(min); start[in]++; } printf("%u\n", num[n]); return 0; }

  • USACO 3.1.2 Score Inflation 解题报告

    这题和第三章第一题一样,标准的无限01背包,直接把代码放进去就可以了,代码: / LANG: C ID: yylogoo1 PROG: inflate / #include int f[10001]; #define max(a, b) ((a)<(b)?(a):(b)) int main(void) { int m, n; int i, j; int a, b; freopen("inflate.in", "r", stdin); freopen("inflate.out", "w", stdout); scanf("%d%d", &m, &n); for(i = 0; i <n i scanfdd a b forj="b;" j="m;" j fj="max(f[j" - b a fj printfdn fm return code>

  • USACO 3.1.1 Agri-Net 解题报告

    这题的话,是最小生成树的标准题,但是最小生成树我不记得写了,后来想起来了之后发现这个二叉堆实现很麻烦,就看看标称的二叉堆是怎么实现的,结果标称直接暴力就是,呵呵,感觉有点投机取巧,因为数据小所以这样。 晚点捉摸下二叉堆的实现,先把这题的代码贴上来(暴力搜的) / LANG: C ID: yylogoo1 PROG: agrinet / #include int map[100][100]; int used[100]; int main(void) { int i, j, k, l; int n; int ans = 0, t; freopen("agrinet.in", "r", stdin); freopen("agrinet.out", "w", stdout); scanf("%d", &n); for(i = 0; i

  • USACO 2.4.5 Fractions to Decimals 解题报告

    这题的话,其实也好说,就是利用余数进行判断,看代码吧: de lang="C">/ LANG: C ID: yylogoo1 PROG: fracdec / #include int num[100001]; int mod[100001]; char str[77]; int len; void add(char ch) { if(len == 76){ printf("%s\n", str); str[0] = ‘\0’; len = 0; } str[len++] = ch; } void output(int start, int end) { int i; for(i = start; i

  • USACO 2.4.4 comehome 解题报告

    这一题其实很简单,只是有个陷阱,考验你们细心与否,就是两个牧场之间可能不只有一条路径,所以这里注意一下就不会出大问题,代码如下所示: de lang="c">/ LANG: C ID: yylogoo1 PROG: comehome / #include #define INF 0xFFFFFF int map[52][52]; int getnum(char c) { if(c <= ‘a’ && c map[i][k] + map[k][j]){ map[i][j] = map[i][k] + map[k][j]; } } } } for(i = 26; i <51 i ifmin> map[i][51]){ c = i – 26; min = map[i][51]; } } printf("%c %d\n", c + ‘A’, min); return 0; } de>

  • USACO 2.4.3 Cow Tours 解题报告

    这个题目涉及的算法真的好多好多,一下子还真摸不着头脑,但摸着没摸着都先听我说。 首先要把链接在一起的那些牧区之间的距离算出来(勾股定理),然后要把各个牧场的牧区标示出来(洪水填充),这样就能进行下一步了,再把各个节点之间的距离算出来,用floyd-warshall算法,O(n^3)的那个算法,然后,再把每个牧区在这个牧场距离最远的节点之间的距离算出来,再把每个牧场的直径算出来,这题目就大概出来了。 最后在循环两个牧区,如果是在一个牧场就退出循环,如果是在两个不同的牧场的话,那如果连接起来这个新的牧场的直径就有三种可能:a牧区所在的牧场的直径;b牧区所在的牧场的直径;a牧区在牧场中距离最远的距离加上b牧区在牧场中距离最远的距离再加上a,b之间的距离。 代码如下: / LANG: C ID: yylogoo1 PROG: cowtour / #include #include #define INF 1000000.0 int x[150], y[150]; double map[150][150]; int group[150]; int n; double getdis(int i, int j) { return sqrt((x[i] - x[j]) (x[i] - x[j]) + (y[i] - y[j]) (y[i] - y[j])); } void fool(int a, int k) { int i; if(group[a]){ return; } group[a] = k; for(i = 0; i b ? a : b; } int main(void) { int i, j, k; int ch; double max, t; freopen("cowtour.in", "r", stdin); freopen("cowtour.out", "w", stdout); scanf("%d\n", &n); for(i = 0; i map[i][k] + map[k][j]){ map[i][j] = map[i][k] + map[k][j]; } } } } for(i = 0; i

  • USACO 2.4.2 Overfencing 解题报告

    题目看了之后容易发现就是广搜,从两个入口对全图进行广搜,搜到最后一个所需要的路程就是答案,广搜实现一点儿也不难,我的实现感觉还是比较好的,用一个宏和一个函数实现这个功能,然后用数字代表前进的方向,0:北,1:南,2:西,3:东。 但这题难的地方我觉得是把图转化成数据和寻找入口,其实难也不难,只是希望实现的代码简单些。刚开始我想根据变量循环的位置来判断,但这种方法的弊端就是代码量太大,要好多好多的判断,难的写,就直接使用-和|(墙的标识。)来标记数据就可以了,发现这个实现很简单,但是麻烦的就是找入口,最后我还是用了好多代码。 最开始我是把图转化成为数组的值之后再在数组里寻找,这么实现的话可以,只是说代码要多好几行,就换了种方法,放到和读取数据的循环了(看不懂这些话就看代码吧。) 代码: de lang="c">/ LANG: C ID: yylogoo1 PROG: maze1 / #include #include #define UP 1 #define DOWN 2 #define LEFT 4 #define RIGHT 8 //为0和39都提供空间, 在程序处理中会方便些 int map[102][40]; int ways[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; int queue[3800][2]; int mark[101][39]; int head, end; int w, h; void enqueue(int i, int j, int k) { if(mark[i][j]){ return; } queue[end][0] = i; queue[end][1] = j; mark[i][j] = k; end++; } void exqueue(int *a) { assert(head h || b <1 b> w){ return 0; } return 1; } int main(void) { int i, j; char ch; int t[2]; freopen("maze1.in", "r", stdin); freopen("maze1.out", "w", stdout); scanf("%d%d\n", &w, &h); for(i = 1; i <2>