糯米

TI DaVinci, gstreamer, ffmpeg
随笔 - 167, 文章 - 0, 评论 - 47, 引用 - 0
数据加载中……

POJ 1951 Extra Krunch 恶心题

注意:
符号前面不能有空格。
开头末尾不能有空格。

#include <stdio.h>

char set[256], src[256], dst[256];

int main()
{
    
char *s, *d, blank;

    freopen(
"e:\\test\\in.txt""r", stdin);

    
set['A'= set['E'= set['I'= set['O'= set['U'= 1;
    fgets(src, 
sizeof(src), stdin);
    dst[
0= ' ';
    d 
= dst + 1;
    s 
= src;
    
while (*s) {
        
if (*>= 'A' && *<= 'Z'{
            
if (!set[*s])
                
*d++ = *s;
            
set[*s] = 1;
        }
 else if (*== ' '{
            
if (d[-1!= ' ')
                
*d++ = ' ';
        }
 else {
            
if (d[-1== ' ')
                d
--;
            
*d++ = *s;
        }

        s
++;
    }

    
while (*--== ' ');
    
*= 0;
    printf(
"%s\n", dst + 1);

    
return 0;
}


posted @ 2010-03-14 01:10 糯米 阅读(411) | 评论 (0)编辑 收藏

POJ 1258 Agri-Net 最小生成树

朴素的Prim!

#include <stdio.h>

int map[128][128], set[128], N, tm;

__inline 
int prim()
{
    
int sum, i, j, k, min_val, min_idx;

    tm
++;
    
set[0= tm;
    sum 
= 0;
    
for (i = 0; i < N - 1; i++{
        min_val 
= 0x7fffffff;
        
for (j = 0; j < N; j++{
            
if (set[j] != tm)
                
continue;
            
for (k = 0; k < N; k++{
                
if (set[k] != tm && map[j][k] < min_val) {
                    min_val 
= map[j][k];
                    min_idx 
= k;
                }

            }

        }

        sum 
+= min_val;
        
set[min_idx] = tm;
    }


    
return sum;
}


int main()
{
    
int i, j;

    freopen(
"e:\\test\\in.txt""r", stdin);

    
while (scanf("%d"&N) != EOF) {
        
for (i = 0; i < N; i++)
            
for (j = 0; j < N; j++)
                scanf(
"%d"&map[i][j]);
        printf(
"%d\n", prim());
    }


    
return 0;
}

posted @ 2010-03-14 00:42 糯米 阅读(122) | 评论 (0)编辑 收藏

POJ 2387 Til the Cows Come Home 单源最短路径

用的SPFA算法。

#include <stdio.h>
#include 
<stdlib.h>

#define MAX_N 1024
#define MAX_T 2048

struct edge_node {
    
int idx, len;
    
struct edge_node *next;
}
;
struct edge_node edges[MAX_T * 2], *map[MAX_N];
int N, T, D[MAX_N], queue[MAX_N], qh, qt, visited[MAX_N];

__inline 
void add_edge(struct edge_node *e, int from, int to, int len)
{
    e
->idx = to;
    e
->len = len;
    e
->next = map[from];
    map[from] 
= e;
}


int main()
{
    
int i, from, to, len;
    
struct edge_node *e;

    freopen(
"e:\\test\\in.txt""r", stdin);
        
    scanf(
"%d%d"&T, &N);
    
for (i = 0; i < T * 2; i += 2{
        scanf(
"%d%d%d"&from, &to, &len);
        add_edge(
&edges[i], from, to, len);
        add_edge(
&edges[i + 1], to, from, len);
    }

    
    
for (i = 1; i <= N; i++)
        D[i] 
= 0x00ffffff;

    queue[
0= N;
    visited[N] 
= 1;
    D[N] 
= 0;
    qh 
= 0;
    qt 
= 1;
    
while (qh != qt) {
        i 
= queue[qh++];
        qh 
&= _countof(queue) - 1;
        visited[i] 
= 0;
        
for (e = map[i]; e; e = e->next) {
            
if (D[i] + e->len < D[e->idx]) {
                D[e
->idx] = D[i] + e->len;
                
if (!visited[e->idx]) {
                    visited[e
->idx] = 1;
                    queue[qt
++= e->idx;
                    qt 
&= _countof(queue) - 1;
                }

            }

        }

    }

    printf(
"%d\n", D[1]);

    
return 0;
}

posted @ 2010-03-14 00:21 糯米 阅读(316) | 评论 (0)编辑 收藏

POJ 2389 Bull Math 高精度整数

注意:
要去掉前面的0再输出。


#include <stdio.h>
#include 
<string.h>

struct node {
    
char arr[128];
    
int len;
}
;

__inline 
int max(int a, int b)
{
    
return a > b ? a : b;
}


__inline 
void add(struct node *a, struct node *b)
{
    
int i, val;

    
for (val = i = 0; i < max(a->len, b->len); i++{
        
if (i < a->len)
            val 
+= a->arr[i];
        
if (i < b->len)
            val 
+= b->arr[i];
        a
->arr[i] = val % 10;
        val 
/= 10;
    }

    
if (val)
        a
->arr[i++= val;
    a
->len = i;
}


__inline 
void mul_single(struct node *a, int val, int pad, struct node *c)
{
    
int i, r;

    
for (i = 0; i < pad; i++)
        c
->arr[i] = 0;
    c
->len = pad;
    
for (r = i = 0; i < a->len; i++{
        r 
+= a->arr[i] * val;
        c
->arr[c->len++= r % 10;
        r 
/= 10;
    }

    
if (r)
        c
->arr[c->len++= r;
}


__inline 
void mul(struct node *a, struct node *b, struct node *c)
{
    
struct node t;
    
int i;

    c
->len = 0;
    
for (i = 0; i < a->len; i++{
        mul_single(b, a
->arr[i], i, &t);
        add(c, 
&t);
    }

}


__inline 
void input(struct node *t)
{
    
char str[sizeof(t->arr)];
    
int i, len;

    scanf(
"%s", str);
    len 
= strlen(str);
    t
->len = 0;
    
for (i = len - 1; i >= 0; i--)
        t
->arr[t->len++= str[i] - '0';
}


__inline 
void output(struct node *t)
{
    
int i;

    
for (i = t->len - 1; i >= 0 && !t->arr[i]; i--);
    
if (i < 0{
        printf(
"0\n");
        
return ;
    }

    
for ( ; i >= 0; i--)
        putc(t
->arr[i] + '0', stdout);
    putc(
'\n', stdout);
}


int main()
{
    
struct node a, b, c;

    freopen(
"e:\\test\\in.txt""r", stdin);

    input(
&a);
    input(
&b);
    mul(
&a, &b, &c);
    output(
&c);

    
return 0;
}

posted @ 2010-03-14 00:08 糯米 阅读(237) | 评论 (0)编辑 收藏

POJ 1988 Cube Stacking 并查集

纪念一下,跟我生日一样的题目。
思路:
这题可以用并查集来做,也是挺取巧的。
每个栈看做是一个集合,用一个数组记录栈中元素离栈底的距离,一个数组记录每个栈底元素对应的栈顶的元素。
对于移动操作,只需要合并集合,然后更改栈顶元素数组就行了。

用了栈写的路径压缩,代码跑到230ms。不知道那些100ms是怎么搞出来的。。真的有什么神奇技巧吗。

#include <stdio.h>

#define MAX_N 30032

int top[MAX_N];
struct set_node {
    
int parent, dis;
}
;
struct set_node set[MAX_N];

__inline 
int find(int idx)
{
    
static int stk[MAX_N], sp, i;

    
for (sp = 0set[idx].parent; sp++{
        stk[sp] 
= idx;
        idx 
= set[idx].parent;
    }

    
for (sp--; sp >= 0; sp--{
        i 
= stk[sp];
        
set[i].dis += set[set[i].parent].dis;
        
set[i].parent = idx;
    }


    
return idx;
}


int main()
{
    
int p, a, b;
    
char op[16];

    freopen(
"e:\\test\\in.txt""r", stdin);

    
for (a = 0; a < MAX_N; a++)
        top[a] 
= a;

    scanf(
"%d"&p);
    
while (p--{
        scanf(
"%s%d", op, &a);
        
if (op[0== 'M'{
            scanf(
"%d"&b);
            a 
= find(a);
            b 
= find(b);
            
set[a].parent = top[b];
            
set[a].dis = 1;
            top[b] 
= top[a];
        }
 else {
            find(a);
            printf(
"%d\n"set[a].dis);
        }

    }


    
return 0;
}

posted @ 2010-03-13 23:07 糯米 阅读(222) | 评论 (0)编辑 收藏

POJ 2385 Apple Catching 动态规划

思路:
由于W的值 <= 30,比较小,所以这题可以用动态规划来做。
首先要把连续同一个数字一次处理。
dp[i] = {走了 i 次以后,得到的最大的苹果数目}。这个数组的大小为 W。
走了奇数次以后,一定位于树2下面。
走了偶数次以后,一定位于树1下面。
假设当前是在第 t 时刻掉了 cnt 个苹果下来。val 表示哪棵树掉的苹果,则执行下面的操作更新数组就可以了。
    if (val == 1{
        
for (i = 0; i <= min(t, W); i += 2)
            dp[i] 
+= cnt;
        
for (i = 1; i <= min(t, W); i += 2
            dp[i 
+ 1= max(dp[i + 1], dp[i] + cnt);
    }
 else {
        
for (i = 1; i <= min(t, W); i += 2)
            dp[i] 
+= cnt;
        
for (i = 0; i <= min(t, W); i += 2)
            dp[i 
+ 1= max(dp[i + 1], dp[i] + cnt);
    }

转移方程就是这个,还是挺简单的。

因为数据弱,代码 0ms ac了。

完整代码:
#include <stdio.h>

int T, W, dp[35], t;

__inline 
int max(int a, int b)
{
    
return a > b ? a : b;
}


__inline 
int min(int a, int b)
{
    
return a < b ? a : b;
}


__inline 
void calc(int val, int cnt)
{
    
int i;

    
if (val == 1{
        
for (i = 0; i <= min(t, W); i += 2)
            dp[i] 
+= cnt;
        
for (i = 1; i <= min(t, W); i += 2
            dp[i 
+ 1= max(dp[i + 1], dp[i] + cnt);
    }
 else {
        
for (i = 1; i <= min(t, W); i += 2)
            dp[i] 
+= cnt;
        
for (i = 0; i <= min(t, W); i += 2)
            dp[i 
+ 1= max(dp[i + 1], dp[i] + cnt);
    }

    t
++;
}


int main()
{
    
int i, pre, cnt;

    freopen(
"e:\\test\\in.txt""r", stdin);

    scanf(
"%d%d%d"&T, &W, &pre);
    cnt 
= 1;
    
while (--T) {
        scanf(
"%d"&i);
        
if (i == pre) {
            cnt
++;
            
continue;
        }

        calc(pre, cnt);
        cnt 
= 1;
        pre 
= i;
    }

    calc(pre, cnt);

    cnt 
= 0;
    
for (i = 0; i <= W; i++)
        cnt 
= max(cnt, dp[i]);
    printf(
"%d\n", cnt);

    
return 0;
}

posted @ 2010-03-13 20:36 糯米 阅读(766) | 评论 (1)编辑 收藏

POJ 2010 Moo University - Financial Aid 堆

昨天做了2008,今天准备做2009。但是看了下题目,发现爆难,才100个人过。
觉得这种题还是别碰了,等以后牛逼了再做。
于是跳过2008年,直接到2010年了!呵呵。

这题还是算容易的,比较适合自己水平发挥,用堆来做,速度尚可 188ms 。


思路:
先把牛按照score排序一下,然后从后往前找,把每一头牛当做是位于中间的那头牛。
那现在就是求:
该头牛前面的所有牛中,哪 (N - 1) / 2 头牛aid值的和最小。
该头牛后面的所有牛中,哪 (N - 1) / 2 头牛aid值的和最小。
这就是典型的用堆可以解决的问题了。

#include <stdio.h>
#include 
<stdlib.h>

#define MAX_C 100032
#define MAX_N 20032

struct node {
    
int score, aid;
}
;
struct node in[MAX_C];
int N, C, F;
int after[MAX_C], before[MAX_C];
int heap_size, heap_sum, heap[MAX_N];

int cmp(const void *a, const void *b)
{
    
return ((struct node *)a)->score - ((struct node *)b)->score;
}


__inline 
void shift_down(int idx)
{
    
int val = heap[idx];
    
while (1{
        idx 
*= 2;
        
if (idx > heap_size)
            
break ;
        
if (idx + 1 <= heap_size && heap[idx + 1> heap[idx])
            idx
++;
        
if (heap[idx] <= val)
            
break;
        heap[idx 
/ 2= heap[idx];
    }

    heap[idx 
/ 2= val;
}


__inline 
int heap_init(int start, int len)
{
    
int i;

    heap_sum 
= 0;
    
for (i = start; i < start + len; i++{
        heap[i 
- start + 1= in[i].aid;
        heap_sum 
+= in[i].aid;
    }

    
for (i = heap_size / 2; i >= 1; i--
        shift_down(i);
    
return heap_sum;
}


__inline 
int heap_update(int aid)
{
    
if (aid < heap[1]) {
        heap_sum 
-= heap[1- aid;
        heap[
1= aid;
        shift_down(
1);
    }

    
return heap_sum;
}


int main()
{
    
int i;

    freopen(
"e:\\test\\in.txt""r", stdin);

    scanf(
"%d%d%d"&N, &C, &F);
    
for (i = 0; i < C; i++)
        scanf(
"%d%d"&in[i].score, &in[i].aid);
    qsort(
in, C, sizeof(in[0]), cmp);
    
    heap_size 
= (N - 1/ 2;
    before[heap_size 
- 1= heap_init(0, heap_size);
    
for (i = heap_size; i < C; i++
        before[i] 
= heap_update(in[i].aid);
    after[C 
- heap_size] = heap_init(C - heap_size, heap_size);
    
for (i = C - heap_size - 1; i >= 0; i--)
        after[i] 
= heap_update(in[i].aid);
    
for (i = C - heap_size - 1; i - heap_size >= 0; i--{
        
if (in[i].aid + before[i - 1+ after[i + 1<= F)
            
break;
    }

    printf(
"%d\n", i - heap_size < 0 ? -1 : in[i].score);

    
return 0;
}

posted @ 2010-03-13 19:25 糯米 阅读(602) | 评论 (0)编辑 收藏

POJ 2008 Moo University - Team Tryouts 牛题

思路:
这道题目的解法非常牛逼。刚一看题就知道做不出来了,所以就在这个博客
http://hi.baidu.com/findthegateopen/
找到了一份解题报告。下面的内容都是基于原作者的代码参考出来的。感谢原作者的代码!

朴素的做法是O(N^3)的复杂度。usaco官方的算法是O(N^2)的复杂度。原作者的代码跑了不到100ms,应该说是相当不错了!

首先,要把所有牛放到坐标系上来表示。目的,就是求出包含最多点的直角三角形。
直角三角形的两条直角边上都必须有点,也就是一组牛中的具有最小height的点和具有最小width的点。
直角三角形的边长也是固定的,cw = C/B,ch = C/A。这个还好说,从那个限制条件可以推出来的。初中都学过,呵呵。



Step1:求出经过一个点的所有可能存在的三角形。
其实也就是在该点下方的灰色区域中选择点来确定一个三角形。




Step2:求出经过一个点的所有可能存在的三角形中,最多包含的点数。
解法相当精妙。

求一个三角形内的点数,可以分解为一个矩形内的点数减去一个梯形内的点数。

用这个方法,求出最上面那个三角形的点数之后。可以继续递推得到下面其他三角形的点数。

也就是加上一个矩形,再减去一个梯形。
如果点按照高度排序以后,那么后面矩形里的点一定是后出现的。这样就可以做到随时增加矩形。
但是减去梯形这个操作,就难理解一点,把点按照A*H + B*W来排序,就能保证后面梯形里的点一定是后出现的。

可见,A*H + B*W 值的大小决定了他们的位置分布。完全可以保证这个顺序。
这种数形结合的方法实在是相当精妙!

那我们就可以首先求出第一个三角形的点数,然后接下来的三角形就根据减去梯形,和增加矩形的操作,来做小的调整就可以了。
在代码里面的表现形式就是维护两个指针,不断向后移,中间剔除横坐标不在范围之内的点。
这个操作的复杂度是O(N)。
对所有点执行一次,故算法的复杂度是O(N^2)。


代码:
/*
 *    本代码参考自 
http://hi.baidu.com/findthegateopen/
 *    中的代码,感谢原作者的代码!
 
*/

#include 
<stdio.h>
#include 
<stdlib.h>

#define MAX_N 1024

struct node {
    
int w, h, k;
}
;

struct node in[MAX_N], *sort_h[MAX_N], *sort_k[MAX_N];
int A, B, C, N, ch, cw, ans, box, slash, cnt;

int cmp_h(const void *a, const void *b)
{
    
return (*(struct node **)b)->- (*(struct node **)a)->h;
}


int cmp_k(const void *a, const void *b)
{
    
return (*(struct node **)b)->- (*(struct node **)a)->k;
}


__inline 
void update(int h, int w)
{
    
int k;

    
for ( ; box < N && sort_h[box]->>= h; box++)
        
if (sort_h[box]->>= w && sort_h[box]-><= w + cw)
            cnt
++;
    k 
= A * h + B * w + C;
    
for ( ; slash < N && sort_k[slash]->> k; slash++)
        
if (sort_k[slash]->>= w && sort_k[slash]-><= w + cw)
            cnt
--;
    
if (cnt > ans)
        ans 
= cnt;
}


__inline 
void calc(int i)
{
    
int h, w;

    box 
= 0;
    slash 
= 0;
    cnt 
= 0;
    h 
= sort_h[i]->h;
    w 
= sort_h[i]->w;
    
for ( ; i < N && sort_h[i]->>= h - ch; i++
        
if (sort_h[i]->>= w && sort_h[i]-><= w + cw)
            update(sort_h[i]
->h, w);
}


int main()
{
    
int i;

    freopen(
"e:\\test\\in.txt""r", stdin);

    scanf(
"%d%d%d%d"&N, &A, &B, &C);
    cw 
= C/B;
    ch 
= C/A;
    
for (i = 0; i < N; i++{
        scanf(
"%d%d"&in[i].h, &in[i].w);
        
in[i].k = A * in[i].h + B * in[i].w;
        sort_h[i] 
= &in[i];
        sort_k[i] 
= &in[i];
    }

    qsort(sort_h, N, 
sizeof(sort_h[0]), cmp_h);
    qsort(sort_k, N, 
sizeof(sort_k[0]), cmp_k);

    
for (i = 0; i < N; i++)
        calc(i);
    printf(
"%d\n", ans);

    
return 0;
}



posted @ 2010-03-12 20:07 糯米 阅读(1110) | 评论 (0)编辑 收藏

POJ 1985 Cow Marathon 动态规划/深搜

思路:
1985也可以用1986的程序改改就行了。
但是觉得不用什么算法也是可以做出1985的。

想了一下,发现:
路径的最大值一定存在于两个叶子节点中。
如果只有一个叶子,那整个树就是一条直线了。

由于我们只是考虑叶子节点。那么对于每一个非叶子节点,我们只需要找出它下面的所有节点中,离它最远的两个叶子就行了。
这两个叶子节点的距离也就有可能成为答案。
对于每个点,我们只需要保存一个值,就是该点下面的所有节点中,距离它最远的一个叶子节点,和它的距离。
对于每个点,遍历完它的孩子之后,就知道“离它最远的两个叶子的距离”了。

注意:
代码里需要处理“一条直线连着几个点”这种情况,将这样的几个点缩成一个点比较好。不做这个处理一定会爆栈。最后一个数据是一条直线。(阴险)

这份代码跑了141MS,还算可以,呵呵。应该比直接用lca要快。

#include <stdio.h>

#define MAX_N 40032

struct edge_node {
    
struct edge_node *next;
    
int idx, len;
}
;
struct edge_node edges[MAX_N*2];

struct tree_node {
    
struct edge_node *edge;
    
int visited;
}
;
struct tree_node tree[MAX_N];
int max_val;

__inline 
void add_edge(int idx, int a, int b, int len)
{
    
struct edge_node *= &edges[idx];
    e
->idx = b;
    e
->len = len;
    e
->next = tree[a].edge;
    tree[a].edge 
= e;
}


int dfs(int idx)
{
    
struct edge_node *e;
    
int sum, cnt, arr[2], r;

    sum 
= 0;
    
while (1{
        tree[idx].visited 
= 1;
        cnt 
= 0;
        
for (e = tree[idx].edge; e; e = e->next)
            cnt 
+= !tree[e->idx].visited;
        
if (!cnt)
            
return sum;
        
if (cnt > 1)
            
break;
        
for (e = tree[idx].edge; tree[e->idx].visited; e = e->next);
        sum 
+= e->len;
        idx 
= e->idx;
    }


    arr[
0= arr[1= 0;
    
for (e = tree[idx].edge; e; e = e->next) {
        
if (tree[e->idx].visited)
            
continue;
        r 
= dfs(e->idx) + e->len;
        
if (r >= arr[1]) {
            arr[
0= arr[1];
            arr[
1= r;
        }
 else if (r >= arr[0])
            arr[
0= r;
    }


    r 
= arr[0+ arr[1];
    
if (r > max_val)
        max_val 
= r;

    
return arr[1+ sum;
}


int main()
{
    
int m, n, a, b, len, i;
    
char str[16];

    freopen(
"e:\\test\\in.txt""r", stdin);

    scanf(
"%d%d"&n, &m);
    
for (i = 0; i < m*2; i += 2{
        scanf(
"%d%d%d%s"&a, &b, &len, str);
        add_edge(i, a, b, len);
        add_edge(i 
+ 1, b, a, len);
    }


    
for (i = 1; i <= n; i++{
        
if (tree[i].visited)
            
continue;
        a 
= dfs(i);
        
if (a > max_val)
            max_val 
= a;
    }

    printf(
"%d\n", max_val);

    
return 0;
}



posted @ 2010-03-10 19:14 糯米 阅读(644) | 评论 (0)编辑 收藏

POJ 1986 Distance Queries 最近公共祖先

     摘要: 以前没见过“最近公共祖先”这一类的题啊。长见识了,呵呵。解法基本上就是http://www.cppblog.com/varg-vikernes/archive/2010/03/10/109355.html这篇文章里面提到的两种方法。两种方法的解法都非常精妙!最后程序写出来:Tarjan 3372K 219MSDFS+RMQ 7992K 329MS代码Tarjan:...  阅读全文

posted @ 2010-03-10 16:14 糯米 阅读(1269) | 评论 (0)编辑 收藏

仅列出标题
共17页: First 9 10 11 12 13 14 15 16 17