糯米

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

POJ 1476 Always On the Run 动态规划

这题做得人特别少,但实际上就是很普通的动态规划。

思路:
由于飞到某个点的时候,后面的行程跟前面的行程没有什么联系,所以开一个二维数组 f[K][N],
f[i][j] = { 从第 j 个点,第 i 个时刻开始飞行直到终点,所需要的最小花费 }

然后就从后往前推就可以了。

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

#define MAX_N 16
#define MAX_D 32
#define INFINITE 100000

struct node {
    
int arr[MAX_D], cnt;
}
;
struct node map[MAX_N][MAX_N];
int N, K;

__inline 
void input()
{
    
int i, j, k;
    
struct node *t;

    
for (i = 1; i <= N; i++{
        
for (j = 1; j <= N; j++{
            
if (i == j)
                
continue;
            t 
= &map[i][j];
            scanf(
"%d"&t->cnt);
            
for (k = 0; k < t->cnt; k++)
                scanf(
"%d"&t->arr[k]);
        }

    }

}


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


__inline 
void solve(int sc)
{
    
int dp[2][MAX_N], *cur, *nxt, i, j, k, val;
    
struct node *t;

    memset(dp, 
0sizeof(dp));
    dp[
0][N] = 1;
    
for (i = K - 1; i >= 0; i--{
        cur 
= dp[(K - 1 - i) & 1];
        nxt 
= dp[(K - i) & 1];
        
for (j = 1; j <= N; j++{
            nxt[j] 
= 0;
            
for (k = 1; k <= N; k++{
                
if (j == k || !cur[k])
                    
continue;
                t 
= &map[j][k];
                val 
= t->arr[i % t->cnt];
                
if (!val)
                    
continue;
                val 
+= cur[k];
                
if (!nxt[j] || val < nxt[j])
                    nxt[j] 
= val;
            }

        }

    }

    printf(
"Scenario #%d\n", sc);
    
if (nxt[1])
        printf(
"The best flight costs %d.\n\n", nxt[1- 1);
    
else
        printf(
"No flight possible.\n\n");
}


int main()
{
    
int i;

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

    
for (i = 1; scanf("%d%d"&N, &K), N; i++{
        input();
        solve(i);
    }

}

posted @ 2010-03-30 16:29 糯米 阅读(308) | 评论 (0)编辑 收藏

POJ 1475 Pushing Boxes 推箱子游戏 宽搜

     摘要: 思路:这题就是平常玩的那种推箱子的游戏。不过简化了一下,只是推一个箱子而已。用 bfs 来做,搜索树里面的节点,也就是状态,可以定义为:1. 箱子的坐标2. 上一次推完之后,人要走多少步才能到达箱子的上、下、左、右侧。如果到达不了,值则为无穷大。这样,状态转移的时候。就首先看是否能向某个方向推。如果能的话,就推一下。然后对人进行一次 bfs ,看下此时到达箱子的各个侧要走多少步。就可以生成一个新的...  阅读全文

posted @ 2010-03-30 09:07 糯米 阅读(769) | 评论 (0)编辑 收藏

POJ 3168 Barn Expansion 快排

思路:

一开始想到用线段树来做,但是发现坐标范围异常的大,放一个都勉勉强强,更不用说几个了!
想了一下,发现有一个至关重要的条件“不存在覆盖的情况”。
那就没必要用线段树了,因为压根就没必要解决覆盖问题。
可以用一种取巧的方法解决这题。



对于每个矩形,首先把它 y 方向的两条边抽取出来。
对于所有矩形的 y 方向的边,先按照 x 排序,然后按照顶端的 y 坐标排序。



然后对于位于同一 x 坐标的边,找出所有首尾相接或者有交集的边。
那么这些边对应的矩形必定要排除。

对于 x 方向的边,作同样的处理。

排除完之后,剩下的矩形就是可以答案了。

代码 500 多ms。。
#include <stdio.h>
#include 
<stdlib.h>

#define MAX_N 25032

struct node {
    
int barn, start, end, idx;
}
;
struct node vert[MAX_N * 2], hori[MAX_N * 2];
char cannot[MAX_N];
int N, ans;

__inline 
void add_node(struct node *t, int barn, int start, int end, int idx)
{
    t
->barn = barn;
    t
->start = start;
    t
->end = end;
    t
->idx = idx;
}


int cmp_node(const void *a, const void *b)
{
    
struct node *p, *q;
    p 
= (struct node *)a;
    q 
= (struct node *)b;
    
if (p->idx != q->idx)
        
return p->idx - q->idx;
    
return p->start - q->start;
}


__inline 
void disable_barn(int barn)
{
    
if (!cannot[barn]) {
        cannot[barn] 
= 1;
        ans
--;
    }
 
}


__inline 
void calc(struct node *arr, int len)
{
    
int i, idx, end, cnt, first;

    i 
= 0;
    
while (i < len) {
        idx 
= arr[i].idx;
        end 
= arr[i].end;
        first 
= i;
        cnt 
= 0;
        i
++;
        
while (i < len && arr[i].idx == idx && arr[i].start <= end) {
            
if (arr[i].end > end)
                end 
= arr[i].end;
            disable_barn(arr[i].barn);
            cnt
++;
            i
++;
        }

        
if (cnt)
            disable_barn(arr[first].barn);
    }

}


int main()
{
    
int i, top, left, bottom, right;

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

    scanf(
"%d"&N);
    ans 
= N;
    
for (i = 0; i < N; i++{
        scanf(
"%d%d%d%d"&left, &bottom, &right, &top);
        add_node(
&vert[i * 2], i, bottom, top, left);
        add_node(
&vert[i * 2 + 1], i, bottom, top, right);
        add_node(
&hori[i * 2], i, left, right, top);
        add_node(
&hori[i * 2 + 1], i, left, right, bottom);
    }

    qsort(vert, N 
* 2sizeof(vert[0]), cmp_node);
    qsort(hori, N 
* 2sizeof(hori[0]), cmp_node);
    calc(vert, N 
* 2);
    calc(hori, N 
* 2);
    printf(
"%d\n", ans);

    
return 0;
}


posted @ 2010-03-18 15:52 糯米 阅读(634) | 评论 (0)编辑 收藏

POJ 3167 Cow Patterns 牛题

     摘要: 此题只有130人solved!也算小牛题了,刚开始看到的时候,打算不做了的,但后来想了一下,发现有一点点思路。经过好几个小时的奋战,居然做出来了!那感觉非常爽!思路:首先此题的变态之处是,要求比较的是排名,就不是单纯的字符串匹配了。如果每次都重新求排名然后跟pattern比较,复杂度 O(NK),八成会超时。关键是:一,不能每次都重新求排名二,不能逐个逐个的和pattern做比较看来也只有动态规...  阅读全文

posted @ 2010-03-18 15:30 糯米 阅读(1190) | 评论 (2)编辑 收藏

POJ 3175 Finding Bovine Roots 简单计算

思路:
看到这题,第一个想到的方法就是枚举 sqrt(2), sqrt(3), sqrt(4) 。。,然后sprintf出来,再比较字符串。
显然,这种方法比较低级啦。
仔细想了下,发现如果 x.123... 这个数字的平方是一个整数的话,那必然
 sqr(x.124) > ceil(sqr(x.123))  [sqr = 求平方, ceil = 向上取整]
所以,就可以从小到大枚举它的整数部分 x ,遇到第一个满足结果的 x,就是答案了。


代码 0ms AC
#include <stdio.h>
#include 
<math.h>

double A, P, B;
int L;

__inline 
double sqr(double i)
{
    
return i * i;
}


double pow_1[] = {
    
1, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, 1e-10
}
;

int main()
{
    
double i, j;
    
int d;

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

    scanf(
"%d%d"&L, &d);
    P 
= pow_1[L];
    B 
= P * d;
    
for (A = 1; ; A++{
        i 
= (__int64)sqr(A + B) + 1;
        j 
= sqr(A + B + P);
        
if (j > i)
            
break;
    }

    printf(
"%I64d\n", (__int64)i);

    
return 0;
}

posted @ 2010-03-18 08:46 糯米 阅读(444) | 评论 (0)编辑 收藏

POJ 3174 Alignment of the Planets 无语题

     摘要: 这个题目立意很好,但是就是数据比较无语了。O(N^3)的算法都能跑得比 O(N^2LgN)的快。代码写很长,这份应该算比较烂了,连自己都不知道代码的时间复杂度是多少!最终170ms AC,速度不快,比几百行的O(N^3)代码要慢很多。。。注意:用分数保存斜率,可以不触及精度问题,而且还比较方便。提交了很多次都WA,不知道问题所在,于是还写了一个脚本来测数据,然后发现了问题所在。附带脚本和测试数据...  阅读全文

posted @ 2010-03-15 14:23 糯米 阅读(555) | 评论 (0)编辑 收藏

我们的纯真与失落

有人说,宫崎骏只拍过一部片子,叫做《我们的纯真与失落》。

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

POJ 1990 MooFest 树状数组

思路:
开四个树状数组。。
arr_x,arr_y,arr_xy,arr_cnt
分别统计y轴下:x的和、y的和、x*y的和、点的个数。
把点按照x排序,x越大的点出现得越晚。
从前往后推,每出现一个新的点的时候:
Step1,将该点加入到四个数组中。
Step2,对于高于它的点,面积增量为 x*sum(y) - sum(x*y)。
Step3,对于低于它的点,面积增量为 sum(y) * (cnt * x - sum(x))
最终得出结果。复杂度O(NlgN)。代码 63ms。

注意:
需要用int64保存数组元素

#include <stdio.h>

#define MAX_X 20032
#define MAX_Y 20032

int cow[MAX_X], left, top, N;
__int64 arr_x[MAX_Y], arr_y[MAX_Y], arr_xy[MAX_Y], arr_cnt[MAX_Y];

__inline 
int lowbit(int i)
{
    
return i & (i ^ (i - 1));
}


__inline __int64 sum(__int64 
*arr, int i)
{
    __int64 s;
    
    
for (s = 0; i; i -= lowbit(i))
        s 
+= arr[i];
    
return s;
}


__inline 
void insert(__int64 *arr, int i, __int64 val)
{
    
for (; i <= top; i += lowbit(i))
        arr[i] 
+= val;
}


int main()
{
    
int i, x, y;
    __int64 s, sx, sy, sxy, c;

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

    scanf(
"%d"&N);
    left 
= MAX_X;
    
for (i = 0; i < N; i++{
        scanf(
"%d%d"&y, &x);
        
if (x < left)
            left 
= x;
        
if (y > top)
            top 
= y;
        cow[x] 
= y;
    }


    s 
= 0;
    x 
= left - 1;
    
for (i = 0; i < N; i++{
        
for (x++!cow[x]; x++);
        y 
= cow[x];
        insert(arr_x, y, x);
        insert(arr_y, y, y);
        insert(arr_xy, y, x 
* y);
        insert(arr_cnt, y, 
1);
        c 
= sum(arr_cnt, y - 1);
        sx 
= sum(arr_x, y - 1);
        s 
+= c*x*- sx*y;
        sy 
= sum(arr_y, top) - sum(arr_y, y - 1);
        sxy 
= sum(arr_xy, top) - sum(arr_xy, y - 1);
        s 
+= x*sy - sxy;
    }


    printf(
"%I64d\n", s);

    
return 0;
}

posted @ 2010-03-14 17:39 糯米 阅读(386) | 评论 (0)编辑 收藏

POJ 1989 The Cow Lineup 动态规划

思路:
如果之前出现过长度为 len 的子序列。假设该子序列出现在 [a, b] 之间。
那如果存在 1, 2, ... K 任意一个数字出现在 [a, b] 之间,则必然存在一个长度为 len + 1 的非子序列。

代码:
从后往前推。用的是链表。94ms AC。
速度一般,还是不知道那些 0ms 是怎么搞出来的。
有人说可以从前往后推,可能会快一点吧。

#include <stdio.h>

#define MAX_N 100032
#define MAX_K 10032

struct node {
    
int idx;
    
struct node *next;
}
;
struct node nodes[MAX_N], *pos[MAX_K];
int N, K, left;

int main()
{
    
int i, j, len;

    freopen(
"e:\\test\\in.txt""r", stdin);
    
    scanf(
"%d%d"&N, &K);
    
for (i = 0; i < N; i++{
        scanf(
"%d"&j);
        nodes[i].idx 
= i;
        nodes[i].next 
= pos[j];
        pos[j] 
= &nodes[i];
    }


    left 
= N + 1;
    
for (len = 1; len <= N; len++{
        j 
= left;
        
for (i = 1; i <= K; i++{
            
while (pos[i] && pos[i]->idx >= left)
                pos[i] 
= pos[i]->next;
            
if (!pos[i])
                
break;
            
if (pos[i]->idx < j)
                j 
= pos[i]->idx;
        }

        
if (i <= K)
            
break;
        left 
= j;
    }

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

    
return 0;
}

posted @ 2010-03-14 15:46 糯米 阅读(456) | 评论 (0)编辑 收藏

POJ 2132 Cow Math 二分

思路:
首先每条路径的值都可以分解一下质因数,就可以表示为多个质数的幂相乘的形式,
 比如 2^6 * 3^8 * 17^22 * 23^1。

三个数字a, b, c求最大公约数,分解完质因数后:
如果a拥有2^8,b拥有2^10,c拥有2^4。那最大公约数必然拥有2^4,取最小的一个。
对于每个质数 2, 3, 5, 7。。都是这个道理。

如果是求最小公倍数,在刚刚的例子里,就是取最大的一个了。

在点之间行走的过程,可以这样来看。在点1的时候GCF的值是所有质数的最大次幂的乘积。
GCF的值必定是越走越小。
每经过一条路径,CGF各个质因数的幂都必须小于等于路径的对应的值。
就好比路径就只能容纳这么大的流量。然后到达点2的时候,看看哪条路径的流量最大。
看起来像最大流问题,但不是最大流问题。

我们没办法遍历一次图,就求出哪条路径的流量最大。
但由于路径的权值最大才2000,质因数的幂最大也只有11(2^11 = 2048),大不了每个幂都试一次。
用二分法就可以了。

对于每一个质数,求到达点2 的时候的最大的幂。
最后再乘起来,就是答案了。
可见这种方法还是很巧妙的,效率也很高,0ms AC。

注意:
不需要高精度。但需要用__int64来保存答案。

#include <stdio.h>

#define MAX_W 2048
#define MAX_N 32 

int N, visit[MAX_N], map[MAX_N][MAX_N], tm;
int prime[MAX_W], prime_cnt, max_cnt[MAX_W];

int dfs(int idx, int val, int cnt)
{
    
int i, j, k;

    
if (idx == 2)
        
return 1;

    visit[idx] 
= tm;
    
for (i = 1; i <= N; i++{
        
if (visit[i] == tm)
            
continue;
        j 
= map[idx][i];
        
for (k = 0; j && !(j % val); k++)
            j 
/= val;
        
if (k < cnt)
            
continue;
        
if (dfs(i, val, cnt))
            
return 1;
    }


    
return 0;
}


__inline 
int calc(int val, int r)
{
    
int l, m;

    l 
= 0;
    
while (l <= r) {
        m 
= (l + r) / 2;
        tm
++;
        
if (dfs(1, val, m))
            l 
= m + 1;
        
else
            r 
= m - 1;
    }


    
return r;
}


int main()
{
    
int i, j, val, p, cnt;
    __int64 r;

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

    prime[prime_cnt
++= 2;
    
for (i = 3; i < MAX_W; i++{
        
for (j = 0; j < prime_cnt && (i % prime[j]); j++);
        
if (j == prime_cnt)
            prime[prime_cnt
++= i;
    }

    
    scanf(
"%d"&N);
    
for (i = 1; i <= N; i++)
        
for (j = 1; j <= N; j++)
            scanf(
"%d"&map[i][j]);
    
    
for (i = 2; i <= N; i++{
        val 
= map[1][i];
        
for (j = 0; j < prime_cnt && val >= 1; j++{
            p 
= prime[j];
            
for (cnt = 0!(val % p); cnt++)
                val 
/= p;
            
if (cnt > max_cnt[j])
                max_cnt[j] 
= cnt;
        }

    }

    
    
for (i = 0; i < prime_cnt; i++{
        
if (!max_cnt[i])
            
continue;
        max_cnt[i] 
= calc(prime[i], max_cnt[i]);
    }


    r 
= 1;
    
for (i = 0; i < prime_cnt; i++{
        
if (!max_cnt[i])
            
continue;
        
for (cnt = 0; cnt < max_cnt[i]; cnt++)
            r 
*= prime[i];
    }

    printf(
"%I64d\n", r);

    
return 0;
}

posted @ 2010-03-14 14:37 糯米 阅读(613) | 评论 (1)编辑 收藏

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