作者: yylogo

  • USACO 3.1 Shaping Regions 形成的区域 解题报告

    这题二话不说, 用map[i][j]表示坐标为i, j的点是什么颜色的.. 很快就写出来了, 但是内存超过了,, 内存最多16MB.
    没办法, 只好另辟思路, 但是在数据压缩方面我又很弱, 就看标程也花了两三天的时间, 今天终于是看懂了..
    用rect记录所有矩形的坐标以及相应的颜色.
    程序具体的步骤如下:

    输入A, B, N. 记录第一个矩形: (0, 0) (A, B), 颜色为1
    接着读入其余的矩形, 设当前是第i个
    对i之前所有的矩形迭代, 此时迭代到的是第j个.
    判断i是否完全包含j, 即: i.x1 >= j.x1 && i.x2 >= j.x2 && i.y1 <= j.y1 && i.y2 >= j.y2..
    若全包围的话, 将第j个矩形删除.
    如果没包围的话, 就判断i会将j拆分成几个矩形, 并将j删除, 再分别拆分的矩形分别放入rect中.

    /*
    LANG: C
    ID: zqy11001
    PROG: rect1
    */
    #include <stdio.h>
    #include <string.h>
    #define MAX 10001
    #define getint(i) scanf(%d, &i)
    #define loop(i, j, k, l)\\
    if(a.i l b.i){\\
     t = a;\\
     t.j = b.k;\\
     tmp[n++] = t;\\
     a.i = b.i;\\
    }
    
    struct rect{
     int t;
     int x1, x2, y1, y2;
    }rect[MAX];
    int rr;
    int color[2500];
    
    int func(struct rect a, const struct rect b, struct rect *tmp)
    {
     int n;
     struct rect t;
     if(b.x1 >= a.x2 || b.x2 <= a.x1 || b.y1 >= a.y2 || b.y2 <= a.y1){
     return 0;
     }
     if(b.x1 <= a.x1 && b.x2 >= a.x2 && b.y1 <= a.y1 && b.y2 >= a.y2){
     return -1;
     }
    
     n = 0;
     loop(x1, x2, x1, <=);
     loop(x2, x1, x2, >=);
     loop(y1, y2, y1, <=);
     loop(y2, y1, y2, >=);
     return n;
    }
    
    int main(void)
    {
     int n, nr, m;
     int a, b, i, j, k;
     struct rect t[4], cur;
     freopen(rect1.in, r, stdin);
     freopen(rect1.out, w, stdout);
     getint(a);
     getint(b);
     getint(n);
    
     rect[0].x1 = rect[0].y1 = 0;
     rect[0].x2 = a;
     rect[0].y2 = b;
     rect[0].t = 1;
    
     rr = 1;
     for(i = 1; i <= n; i++){
     scanf(%d%d%d%d%d, &rect[rr].x1, &rect[rr].y1, 
     &rect[rr].x2, &rect[rr].y2, &rect[rr].t);
     cur = rect[rr++];
     nr = rr - 1;
     for(j = 0; j < nr; j++){
     m = func(rect[j], cur, t);
     if(!m){
     continue;
     }
     if(m < 0){
     memmove(rect + j, rect + j + 1,
     sizeof(struct rect) * (rr - j - 1));
     j--;
     rr--;
     nr--;
     continue;
     }
     rect[j] = t[--m];
     while(m--){
     rect[rr++] = t[m];
     }
     }
     }
     memset(color, 0, sizeof(color));
     for(i = 0; i < rr; i++){
     color[rect[i].t - 1] += (rect[i].x2 - rect[i].x1) *
     (rect[i].y2 - rect[i].y1);
     }
    
     for(i = 0; i < 2500; i++){
     if(color[i]){
     printf(%d %d\\n, i + 1, color[i]);
     }
     }
     return 0;
    }
  • USACO 3.1 Humble Numbers 丑数 解题报告

    从这一题开始,, 以后题目我就不贴上来了… 自己去看吧..

    这一题开始肯本看不懂,, 后来是反反复复看标程看懂了..

    首先要理解这么一个式子吧(算是式子吧“)

    已经求出了j-1个丑数,, 现在求第j个丑数

    对于每一个素数p乘以一个最小的丑数, 能使积大于第j-1个丑数

    在这些乘积中寻找最小的一个即位第j个丑数.

    用pindex[i]表示对于第i个素数乘以的最小丑数是多少..

    /*
    LANG: C
    ID: zqy11001
    PROG: humble
    */
    #include 
    #include 
    #define MAX 100
    #define getint(i) scanf(%d, &i)
    #define insert(i) hum[count++] = i
    
    long hum[1000001];
    int pindex[MAX];
    int prime[MAX];
    int count;
    
    int main(void)
    {
     int k, n;
     int i;
     int min, m;
     freopen(humble.in, r, stdin);
     freopen(humble.out, w, stdout);
     getint(k);
     getint(n);
     for(i = 0; i < k; i++){
     getint(prime[i]);
     }
    
     insert(1);
     memset(pindex, 0, sizeof(int)*k);
     while(count <= n){
     min = 0x7FFFFFFF;
     for(i = 0; i < k; i++){
     while(prime[i] * hum[pindex[i]] <= hum[count - 1]){
     pindex[i]++;
     }
    
     if(prime[i] * hum[pindex[i]] < min){
     min = prime[i] * hum[pindex[i]];
     m = i;
     }
     }
     insert(min);
     }
    
     printf(%d\\n, hum[n]);
     return 0;
    }
  • USACO 3.1 Score Inflation 总分 解题报告

    Score Inflation

    The more points students score in our contests, the happier we here at the USACO are. We try to design our contests so that people can score as many points as possible, and would like your assistance.

    We have several categories from which problems can be chosen, where a "category" is an unlimited set of contest problems which all require the same amount of time to solve and deserve the same number of points for a correct solution. Your task is write a program which tells the USACO staff how many problems from each category to include in a contest so as to maximize the total number of points in the chosen problems while keeping the total solution time within the length of the contest.

    The input includes the length of the contest, M (1 <= M <= 10,000) (don’t worry, you won’t have to compete in the longer contests until training camp) and N, the number of problem categories, where 1 <= N <= 10,000.

    Each of the subsequent N lines contains two integers describing a category: the first integer tells the number of points a problem from that category is worth (1 <= points <= 10000); the second tells the number of minutes a problem from that category takes to solve (1 <= minutes <= 10000).

    Your program should determine the number of problems we should take from each category to make the highest-scoring contest solvable within the length of the contest. Remember, the number from any category can be any nonnegative integer (0, one, or many). Calculate the maximum number of possible points.

    PROGRAM NAME: inflate
    INPUT FORMAT
    Line 1:  M, N — contest minutes and number of problem classes 
    Lines 2-N+1:  Two integers: the points and minutes for each class

    SAMPLE INPUT (file inflate.in)
    300 4
    100 60
    250 120
    120 100
    35 20

    OUTPUT FORMAT
    A single line with the maximum number of points possible given the constraints.
    SAMPLE OUTPUT (file inflate.out)
    605


    描述
    学生在我们USACO的竞赛中的得分越多我们越高兴。

    我们试着设计我们的竞赛以便人们能尽可能的多得分,这需要你的帮助。

    我们可以从几个种类中选取竞赛的题目,这里的一个"种类"是指一个竞赛题目的集合,解决集合中的题目需要相同多的时间并且能得到相同的分数。你的任务是写一个程序来告诉USACO的职员,应该从每一个种类中选取多少题目,使得解决题目的总耗时在竞赛规定的时间里并且总分最大。输入包括竞赛的时间,M(1 <= M <= 10,000)(不要担心,你要到了训练营中才会有长时间的比赛)和N,"种类"的数目1 <= N <= 10,000。后面的每一行将包括两个整数来描述一个"种类":

    第一个整数说明解决这种题目能得的分数(1 <= points <= 10000),第二整数说明解决这种题目所需的时间(1 <= minutes <= 10000)。你的程序应该确定我们应该从每个"种类"中选多少道题目使得能在竞赛的时间中得到最大的分数。

    来自任意的"种类"的题目数目可能任何非负数(0或更多)。

    计算可能得到的最大分数。

    格式
    PROGRAM NAME: inflate

    INPUT FORMAT:

    (file inflate.in)

    第 1 行: M, N–竞赛的时间和题目"种类"的数目。

    第 2-N+1 行: 两个整数:每个"种类"题目的分数和耗时。

    OUTPUT FORMAT:

    (file inflate.out)

    单独的一行包括那个在给定的限制里可能得到的最大的分数。

    SAMPLE INPUT
    300 4
    100 60
    250 120
    120 100
    35 20
    SAMPLE OUTPUT
    605


    ======================== 华丽的分割线 ========================
      标准的无限背包,, 看<<背包9讲>>

    /*
    LANG: C
    ID: zqy11001
    PROG: inflate
    */
    #include <stdio.h>
    #define getint(i) scanf(%d, &i)
    #define max(a, b) ((a)>(b)?(a):(b))
    
    int f[10001];
    
    int main(void)
    {
     int n, m;
     int i, j, t;
     int a, b;
     freopen(inflate.in, r, stdin);
     freopen(inflate.out, w, stdout);
     getint(m);
     getint(n);
     for(i = 1; i <= n; i++){
     scanf(%d%d, &a, &b);
     for(j = b; j <= 10000; j++){
     t = f[j - b] + a;
     f[j] = max(f[j], t);
     }
     }
     printf(%d\\n, f[m]);
     return 0;
    }
  • USA 3.1 Agri-Net 最短网络 解题报告

    Agri-Net
    Russ Cox
    Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He needs your help, of course.

    Farmer John ordered a high speed connection for his farm and is going to share his connectivity with the other farmers. To minimize cost, he wants to lay the minimum amount of optical fiber to connect his farm to all the other farms.

    Given a list of how much fiber it takes to connect each pair of farms, you must find the minimum amount of fiber needed to connect them all together. Each farm must connect to some other farm such that a packet can flow from any one farm to any other farm.

    The distance between any two farms will not exceed 100,000.

    PROGRAM NAME: agrinet
    INPUT FORMAT
    Line 1:  The number of farms, N (3 <= N <= 100). 
    Line 2..end:  The subsequent lines contain the N x N connectivity matrix, where each element shows the distance from on farm to another. Logically, they are N lines of N space-separated integers. Physically, they are limited in length to 80 characters, so some lines continue onto others. Of course, the diagonal will be 0, since the distance from farm i to itself is not interesting for this problem. 

    SAMPLE INPUT (file agrinet.in)
    4
    0 4 9 21
    4 0 8 17
    9 8 0 16
    21 17 16 0

    OUTPUT FORMAT
    The single output contains the integer length that is the sum of the minimum length of fiber required to connect the entire set of farms.

    SAMPLE OUTPUT (file agrinet.out)
    28

    描述
    农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。当然,他需要你的帮助。约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。为了使花费最少,他想铺设最短的光纤去连接所有的农场。你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案。每两个农场间的距离不会超过100000

    格式
    PROGRAM NAME: agrinet

    INPUT FORMAT:

    (file agrinet.in)

    第一行: 农场的个数,N(3<=N<=100)。

    第二行..结尾: 后来的行包含了一个N*N的矩阵,表示每个农场之间的距离。理论上,他们是N行,每行由N个用空格分隔的数组成,实际上,他们限制在80个字符,因此,某些行会紧接着另一些行。当然,对角线将会是0,因为不会有线路从第i个农场到它本身。

    OUTPUT FORMAT:

    (file agrinet.out)

    只有一个输出,其中包含连接到每个农场的光纤的最小长度。

    SAMPLE INPUT
    4
    0 4 9 21
    4 0 8 17
    9 8 0 16
    21 17 16 0
    SAMPLE OUTPUT
    28



    ======================= 华丽的分割线 =======================
      这一题就是最小生成树的问题, 说来复杂… 自己看数据结构吧..

    /*
    LANG: C
    ID: zqy11001
    PROG: agrinet
    */
    #include <stdio.h>
    #define getint(i) scanf(%d, &i)
    #define MAX 100
    #define INF 1e6
    
    int map[MAX][MAX];
    int visited[MAX];
    int path[MAX];
    
    int main(void)
    {
     int n;
     int i, j, k;
     int min, m, tot = 0;
     freopen(agrinet.in, r, stdin);
     freopen(agrinet.out, w, stdout);
     getint(n);
     for(i = 0; i < n; i++){
     for(j = 0; j < n; j++){
     getint(map[i][j]);
     }
     }
    
     for(i = 0; i < n; i++){
     path[i] = map[0][i];
     }
     visited[0] = 1;
     for(i = 1; i < n; i++){
     min = INF;
     for(j = 0; j < n; j++){
     if(!visited[j] && min > path[j]){
     min = path[j];
     m = j;
     }
     }
     visited[m] = 1;
     tot += min;
     for(j = 0; j < n; j++){
     if(visited[j] == 0 && map[m][j] < path[j]){
     path[j] = map[m][j];
     }
     }
     }
     printf(%d\\n, tot);
     return 0;
    }
  • USACO 2.4 Fractions to Decimals 分数化小数 解题报告

    Fractions to Decimals

    Write a program that will accept a fraction of the form N/D, where N is the numerator and D is the denominator and print the decimal representation. If the decimal representation has a repeating sequence of digits, indicate the sequence by enclosing it in brackets. For example, 1/3 = .33333333…is denoted as 0.(3), and 41/333 = 0.123123123…is denoted as 0.(123). Use xxx.0 to denote an integer. Typical conversions are:

    1/3     =  0.(3)
    22/5    =  4.4
    1/7     =  0.(142857)
    2/2     =  1.0
    3/8     =  0.375
    45/56   =  0.803(571428)

    PROGRAM NAME: fracdec
    INPUT FORMAT
    A single line with two space separated integers, N and D, 1 <= N,D <= 100000.
    SAMPLE INPUT (file fracdec.in)
    45 56

    OUTPUT FORMAT
    The decimal expansion, as detailed above. If the expansion exceeds 76 characters in length, print it on multiple lines with 76 characters per line.
    SAMPLE OUTPUT (file fracdec.out)
    0.803(571428)

    描述
    写一个程序,输入一个形如N/D的分数(N是分子,D是分母),输出它的小数形式。如果小数有循环节的话,把循环节放在一对圆括号中。

    例如, 1/3 =0.33333333 写成0.(3), 41/333 = 0.123123123… 写成0.(123), 用xxx.0 等表示整数。典型的转化例子:

    1/3 = 0.(3)
    22/5 = 4.4
    1/7 = 0.(142857)
    2/2 = 1.0
    3/8 = 0.375
    45/56 = 0.803(571428)
    PROGRAM NAME
    fracdec

    INPUT FORMAT
    单独的一行包括被空格分开的N和D(1 <= N,D <= 100000)。

    SAMPLE INPUT
    (file fracdec.in)

    45 56
    OUTPUT FORMAT
    按照上面规则计算出的小数表达式.如果结果长度大于76,每行输出76个字符.




    SAMPLE OUTPUT
    (file fracdec.out)

    0.803(571428)



    ======================== 华丽的分割线 ========================
      这道题我不好怎么说, 看了标程写的,, 思路比较简单, 只是这种题目重来没做过, 所以不知道怎么下手..
      如果余数相等的话, 那么就已经循环了,, 我用rem来存储余数和非循环小数的个数..

    /*
    LANG: C
    ID: zqy11001
    PROG: fracdec
    */
    #include <stdio.h>
    #define MAX 100010
    #define getint(i) scanf(%d, &i)
    
    int rm[MAX];
    char buf[MAX];
    char dev[MAX];
    int counter;
    
    int main(void)
    {
     int m, n;
     int i, j;
     freopen(fracdec.in, r, stdin);
     freopen(fracdec.out, w, stdout);
     getint(m);
     getint(n);
     sprintf(buf, %d., m/n);
     memset(rm, -1, sizeof(rm));
     m = m % n;
     dev[0] = \'0\';
     for(i = 0; ; i++){
     if(m == 0){
     sprintf(buf + strlen(buf), %s, dev);
     break;
     }
     if(rm[m] != -1){
     sprintf(buf + strlen(buf), %.*s(%s), rm[m], 
     dev, dev + rm[m]);
     break;
     }
     rm[m] = i;
     m *= 10;
     dev[counter++] = m / n + \'0\';
     m = m % n;
    
     }
    
     for(i = 0; i < strlen(buf); i+=76){
     printf(%.76s\\n, buf + i);
     }
     return 0;
    }
  • USACO 2.4 Bessie Come Home 回家 解题报告

    Bessie Come Home
    Kolstad & Burch
    It’s dinner time, and the cows are out in their separate pastures. Farmer John rings the bell so they will start walking to the barn. Your job is to figure out which one cow gets to the barn first (the supplied test data will always have exactly one fastest cow).

    Between milkings, each cow is located in her own pasture, though some pastures have no cows in them. Each pasture is connected by a path to one or more other pastures (potentially including itself). Sometimes, two (potentially self-same) pastures are connected by more than one path. One or more of the pastures has a path to the barn. Thus, all cows have a path to the barn and they always know the shortest path. Of course, cows can go either direction on a path and they all walk at the same speed.

    The pastures are labeled ‘a’..’z’ and ‘A’..’Y’. One cow is in each pasture labeled with a capital letter. No cow is in a pasture labeled with a lower case letter. The barn’s label is `Z’; no cows are in the barn, though.

    PROGRAM NAME: comehome
    INPUT FORMAT
    Line 1:  Integer P (1 <= P <= 10000) the number of paths that interconnect the pastures (and the barn) 
    Line 2..P+1:  Space separated, two letters and an integer: the names of the interconnected pastures/barn and the distance between them (1 <= distance <= 1000) 

    SAMPLE INPUT (file comehome.in)
    5
    A d 6
    B d 3
    C e 9
    d Z 8
    e Z 3

    OUTPUT FORMAT
    A single line containing two items: the capital letter name of the pasture of the cow that arrives first back at the barn, the length of the path followed by that cow.
    SAMPLE OUTPUT (file comehome.out)
    B 11

    描述
    现在是晚餐时间,而母牛们在外面分散的牧场中。农民约翰按响了电铃,所以她们开始向谷仓走去。你的工作是要指出哪只母牛会最先到达谷仓(在给出的测试数据中,总会有且只有一只速度最快的母牛)。在挤奶的时候(晚餐前),每只母牛都在她自己的牧场上,一些牧场上可能没有母牛。每个牧场由一条条道路和一个或多个牧场连接(可能包括自己)。有时,两个牧场(可能是字母相同的)之间会有超过一条道路相连。至少有一个牧场和谷仓之间有道路连接。因此,所有的母牛最后都能到达谷仓,并且母牛总是走最短的路径。当然,母牛能向着任意一方向前进,并且她们以相同的速度前进。牧场被标记为’a’..’z’和’A’..’Y’,在用大写字母表示的牧场中有一只母牛,小写字母中则没有。谷仓的标记是’Z’,注意没有母牛在谷仓中。


    注意’m’和’M’不是一个牧场 否则错误

    格式
    PROGRAM NAME: comehome

    INPUT FORMAT

    第 1 行: 整数 P(1<= P<=10000),表示连接牧场(谷仓)的道路的数目。

    第 2 ..P+1行: 用空格分开的两个字母和一个整数:

    被道路连接牧场的标记和道路的长度(1<=长度<=1000)。

    SAMPLE INPUT
    (file comehome.in)

    5
    A d 6
    B d 3
    C e 9
    d Z 8
    e Z 3
    OUTPUT FORMAT

    单独的一行包含二个项目: 最先到达谷仓的母牛所在的牧场的标记,和这只母牛走过的路径的长度。

    SAMPLE OUTPUT
    (file comehome.out)

    B 11


    ========================= 华丽的分割线 =========================
      这题是自己独立完成的,, 喜一个(以前的话都是看着提示和标程之后完成的..)
      思路的话和上一题的思路差不多,,
    http://zqynux.javaeye.com/blog/626000
      所以这方面我就不怎么说明了, 不过这个题目我从一开始就觉得奇怪, n的上限怎么是10000,, 不过没想太多, 就开始写了…, 写完提交试试,, 没AC,, 看了看数据, 和Z有关的只有一个Z a 100, 才想到这是一个无向带权的图, 稍加修改之后又被卡住了,, 到网上看了一下分析才想起来,, 题目里有这么一句话: "两个牧场(可能是字母相同的)之间会有超过一条道路相连。",, 而我们需要的只是最短的,, 所以我又修改了一下…
      也就是说这个10000是有意义的~! 哈,, 还是怪自己审题不清楚..

    /*
    LANG: C
    ID: zqy11001
    PROG: comehome
    */
    #include <stdio.h>
    #define getint(i) scanf(%d\\n, &i)
    #define getmark(a, i) if(i >= \'A\' && i <= \'Z\'){\\
     a = 26 + i - \'A\';\\
     }else{\\
     a = i - \'a\';\\
     }
    #define MAX 52
    #define INF (1e9)
    
    int map[MAX][MAX];
    int n;
    
    void mark(char i, char j, int t)
    {
     int a, b;
     getmark(a, i);
     getmark(b, j);
     if(map[a][b] != 0){
     if(t < map[a][b]){
     map[a][b] = t;
     map[b][a] = t; 
     }
     return ;
     }
     map[a][b] = t;
     map[b][a] = t;
    }
    
    int main(void)
    {
     int i, j, k, t;
     int min = INF, m;
     char a, b;
     freopen(comehome.in, r, stdin);
     freopen(comehome.out, w, stdout);
     getint(n);
     for(i = 0; i < n; i++){
     scanf(%c %c %d\\n, &a, &b, &t);
     mark(a, b, t);
     }
     for(i = 0; i < MAX; i++){
     for(j = 0; j < MAX; j++){
     if(map[i][j] == 0 && i != j){
     map[i][j] = INF;
     }
     }
     }
    
     for(k = 0; k < MAX; k++)
     for(i = 0; i < MAX; i++)
     for(j = 0; j < MAX; j++){
     if(map[i][j] > map[i][k] + map[k][j]){
     map[i][j] = map[i][k] + map[k][j];
     map[j][i] = map[i][k] + map[k][j];
     }
     }
    
     for(i = 26; i < MAX - 1; i++){
     if(map[i][51] < min && map[i][51] != 0){
     min = map[i][51];
     m = i;
     }
     }
    
     printf(%c %d\\n, m - 26 + \'A\', min);
     return 0;
    }
  • USACO Longest Prefix最长前缀 解题报告

    Longest Prefix
    IOI’96
    The structure of some biological objects is represented by the sequence of their constituents denoted by uppercase letters. Biologists are interested in decomposing a long sequence into shorter ones called primitives.

    We say that a sequence S can be composed from a given set of primitives P if there is a some sequence of (possibly repeated) primitives from the set whose concatenation equals S. Not necessarily all primitives need be present. For instance the sequence ABABACABAABcan be composed from the set of primitives

       {A, AB, BA, CA, BBC}

    The first K characters of S are the prefix of S with length K. Write a program which accepts as input a set of primitives and a sequence of constituents and then computes the length of the longest prefix that can be composed from primitives.

    PROGRAM NAME: prefix
    INPUT FORMAT
    First, the input file contains the list (length 1..200) of primitives (length 1..10) expressed as a series of space-separated strings of upper-case characters on one or more lines. The list of primitives is terminated by a line that contains nothing more than a period (‘.’). No primitive appears twice in the list. Then, the input file contains a sequence S (length 1..200,000) expressed as one or more lines, none of which exceed 76 letters in length. The "newlines" are not part of the string S.
    SAMPLE INPUT (file prefix.in)
    A AB BA CA BBC
    .
    ABABACABAABC

    OUTPUT FORMAT
    A single line containing an integer that is the length of the longest prefix that can be composed from the set P.
    SAMPLE OUTPUT (file prefix.out)
    11

    描述
    在生物学中,一些生物的结构是用包含其要素的大写字母序列来表示的。生物学家对于把长的序列分解成较短的(称之为元素的)序列很感兴趣。

    如果一个集合 P 中的元素可以通过串联(允许重复;串联,相当于 Pascal 中的 “+” 运算符)组成一个序列 S ,那么我们认为序列 S 可以分解为 P 中的元素。并不是所有的元素都必须出现。举个例子,序列 ABABACABAAB 可以分解为下面集合中的元素:

    {A, AB, BA, CA, BBC}

    序列 S 的前面 K 个字符称作 S 中长度为 K 的前缀。设计一个程序,输入一个元素集合以及一个大写字母序列,计算这个序列中(由集合元素组成的)最长的前缀的长度。

    格式
    PROGRAM NAME: prefix

    INPUT FORMAT

    输入数据的开头包括 1..200 个元素(长度为 1..10 )组成的集合,用连续的以空格分开的字符串表示。字母全部是大写,数据可能不止一行。元素集合结束的标志是一个只包含一个 “.” 的行。集合中的元素没有重复。接着是大写字母序列 S ,长度为 1..200,000 ,用一行或者多行的字符串来表示,每行不超过 76 个字符。换行符并不是序列 S 的一部分。

    OUTPUT FORMAT

    只有一行,输出一个整数,表示 S 能够分解成 P 中元素的最长前缀的长度。

    SAMPLE INPUT (file prefix.in)
    A AB BA CA BBC
    .
    ABABACABAABC
    SAMPLE OUTPUT (file prefix.out)
    11


    ============================ 华丽的分割线 ============================
      前两天写出来了,, 忘记发日志了`
      感觉用的这个方法不像是DP(对于DP我还没有特别清楚的概念..),, 其中pre变量存储所有的匹配串(即短的那个字符串.), str是住串(长的那个.), 接下来最关键的是lenth这个变量,, (感觉名字没取好), 这个主串假设分为分为a1 a2 a3 … an, lenth[i]如果是1的话代表在a1 a2 a3 .. ai 都是能够在匹配串匹配..
      说了一些云里雾里的话吧,, 废话不多,, 代码上:

    /*
    LANG: C
    ID: zqy11001
    PROG: prefix
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define getstr(s) scanf(%s, s)
    char pre[401][11];
    int m;
    
    char lenth[200001];
    char str[200000];
    int n;
    
    int main(void)
    {
     int i, j, k;
     int best = 0;
     freopen(prefix.in, r, stdin);
     freopen(prefix.out, w, stdout);
     while(1){
     getstr(pre[m]);
     if(pre[m][0] == \'.\'){
     break;
     }
     m++;
     }
     while(getstr(str + n) == 1){
     n += strlen(str + n);
     }
     lenth[0] = 1;
     best = 0;
     for(i = 0; i < n; i++){
     if(lenth[i]){
     best = i;
     for(j = 0; j < m; j++){
     for(k = 0; ((i + k) < n) && (pre[j][k] != \'\\0\') && 
     (pre[j][k] == str[i + k]); k++){
     ;
     }
     if(pre[j][k] == \'\\0\'){
     lenth[i + k] = 1;
     }
     }
     }
     }
     if (lenth[n])
     best = n;
     printf(%d\\n, best);
     return 0;
    }
  • USACO 2.3 Zero Sum 零的算式和 解题报告

    Zero Sum

    Consider the sequence of digits from 1 through N (where N=9) in increasing order: 1 2 3 … N.

    Now insert either a ‘+’ for addition or a ‘-‘ for subtraction or a ‘ ‘ [blank] to run the digits together between each pair of digits (not in front of the first digit). Calculate the result that of the expression and see if you get zero.

    Write a program that will find all sequences of length N that produce a zero sum.

    PROGRAM NAME: zerosum
    INPUT FORMAT
    A single line with the integer N (3 <= N <= 9).
    SAMPLE INPUT (file zerosum.in)
    7

    OUTPUT FORMAT
    In ASCII order, show each sequence that can create 0 sum with a ‘+’, ‘-‘, or ‘ ‘ between each pair of numbers.
    SAMPLE OUTPUT (file zerosum.out)
    1+2-3+4-5-6+7
    1+2-3-4+5+6-7
    1-2 3+4+5+6+7
    1-2 3-4 5+6 7
    1-2+3+4-5+6-7
    1-2-3-4-5+6+7


    USACO_2.3-3:zerosum零的算式和

    Time Limit:1000MS  Memory Limit:65536K
    Total Submit:6 Accepted:4

    Description

    请考虑一个由1到N(N=3, 4, 5 … 9)的数字组成的递增数列:1 2 3 … N。现在请在数列中插入“+”表示加,或者“-”表示减,抑或是“ ”表示空白,来将每一对数字组合在一起(请不在第一个数字前插入符号)。计算该表达式的结果并注意你是否得到了和为零。请你写一个程序找出所有产生和为零的长度为N的数列。

    Input

    PROGRAM NAME: zerosum

    单独的一行表示整数N (3 <= N <= 9)。


    Output

    按照ASCII码的顺序,输出所有在每对数字间插入“+”, “-”, 或 “ ”后能得到和为零的数列。

    Sample Input


    7

    Sample Output


    1+2-3+4-5-6+7
    1+2-3-4+5+6-7
    1-2 3+4+5+6+7
    1-2 3-4 5+6 7
    1-2+3+4-5+6-7
    1-2-3-4-5+6+7

    ========================= 华丽的分割线 =========================
      一个DFS, 题目说了按ASCII的顺序进行输出, 也就是先’ ‘, 再’+’, 接着’-‘.., 我拿到题目就写了一个程序,, DFS没写错, 就是算和的时候错了. 试着写了几个版本, 都错了..(看样子我还是不怎么滴啊~~ 狂汗”).
      不说多的废话了, 代码贴上来:

    /*
    LANG: C
    ID: zqy11001
    PROG: zerosum
    */
    #include <stdio.h>
    #define getint(i) scanf(%d, &i)
    #define putint(i) printf(%d, i)
    #define ze(now, c) str[now] = c; zero(now + 1);
    #define MAX 200
    
    int n;
    char str[9];
    
    void out(void)
    {
     int i;
     putchar(\'1\');
     for(i = 1; i < n; i++){
     printf(%c%d, str[i], i + 1);
     }
     putchar(\'\\n\');
    }
    
    void zero(int sum, int t, int now, char s)
    {
     if(now == n){
     if(s == \'+\'){
     sum += t;
     }else{
     sum -= t;
     }
     if(sum == 0 && str[0] == \'+\'){
     out();
     }
     return;
     }
     str[now] = \' \';
     zero(sum, t * 10 + now + 1, now + 1, s);
     if(s == \'+\'){
     sum += t;
     }else{
     sum -= t;
     }
     str[now] = \'+\';
     zero(sum, now + 1, now + 1, \'+\');
     str[now] = \'-\';
     zero(sum, now + 1, now + 1, \'-\');
    }
    
    int main(void)
    {
     int i, j;
     freopen(zerosum.in, r, stdin);
     freopen(zerosum.out, w, stdout);
     getint(n);
     zero(0, 0, 0, \'+\');
     return 0;
    }
  • USACO 2.3 Cow Pedigrees 奶牛家谱 解题报告

    Farmer John is considering purchasing a new herd of cows. In this new herd, each mother cow gives birth to two children. The relationships among the cows can easily be represented by one or more binary trees with a total of N (3 <= N < 200) nodes. The trees have these properties:

    The degree of each node is 0 or 2. The degree is the count of the node’s immediate children.
    The height of the tree is equal to K (1 < K <100). The height is the number of nodes on the longest path from the root to any leaf; a leaf is a node with no children.
    How many different possible pedigree structures are there? A pedigree is different if its tree structure differs from that of another pedigree. Output the remainder when the total number of different possible pedigrees is divided by 9901.

    PROGRAM NAME: nocows
    INPUT FORMAT
    Line 1: Two space-separated integers, N and K.
    SAMPLE INPUT (file nocows.in)
    5 3

    OUTPUT FORMAT
    Line 1: One single integer number representing the number of possible pedigrees MODULO 9901.
    SAMPLE OUTPUT (file nocows.out)
    2

    OUTPUT DETAILS
    Two possible pedigrees have 5 nodes and height equal to 3:
               @                   @     
              / \                 / \
             @   @      and      @   @
            / \                     / \
           @   @                   @   @



    USACO_2.3-2:Cow Pedigrees奶牛家谱

    Time Limit:1000MS  Memory Limit:65536K
    Total Submit:1 Accepted:1

    Description

    农民约翰准备购买一群新奶牛。 在这个新的奶牛群中, 每一个母亲奶牛都生两小奶牛。这些奶牛间的关系可以用二叉树来表示。这些二叉树总共有N个节点(3 <= N < 200)。这些二叉树有如下性质:

    每一个节点的度是0或2。度是这个节点的孩子的数目。

    树的高度等于K(1 < K < 100)。高度是从根到任何叶子的最长的路径上的节点的数目; 叶子是指没有孩子的节点。

    有多少不同的家谱结构? 如果一个家谱的树结构不同于另一个的, 那么这两个家谱就是不同的。输出可能的家谱树的个数除以9901的余数。

    Input

    PROGRAM NAME: nocows

    第1行: 两个空格分开的整数, N和K。

    Output

    第 1 行: 一个整数,表示可能的家谱树的个数除以9901的余数。

    Sample Input


    SAMPLE INPUT (file nocows.in)

    5 3

    Sample Output


    SAMPLE OUTPUT (file nocows.out)

    2


    ======================== 华丽的分割线 ========================
      题目是看懂了,, 意思就是说用N个节点构造一个高度为K的二叉树, 且每个节点的度不能为1(即只能要么有两个儿子, 要么就没有没有孩子.), 题目我是理解了, 也清楚得很是用DP.. 但是不太会做.. DP没学好.. (自卑中)
      终于吧DP返程看懂了.~!~!~! 狂High中..
      f[i][j] 代表用i各节点构成最多j层的二叉树有多少种情况, 那么
      f[i][j] = ∑(f[m][j-1] * f[i-1-m][j-1])(m = 1, 2, 3 … i – 1)
      m是左子树的节点个数,, 那么i – m 就是除了左子树节点个数之外的节点个数, 再除根节点, 即 i – m – 1就是右子树的节点个数..
      代码能有两个优化的地方(我能够想到的只有这两个),
      第一个就是在DP方程中f[i][j] 和 f[m][j] 都一定是奇数, 因为如果是偶数的话就不能够构成题目所要求的二叉树了.
      第二个就是数据是能够对折的. 这个我晚点尝试一下.. 现在先把没折半的发一下吧.

    /*
    PROG: nocows
    ID: zqy11001
    LANG: C
    */
    #include <stdio.h>
    
    int f[200][100];
    
    int main(void)
    {
     int n, m;
     int i, j, k;
     freopen(nocows.in, r, stdin);
     freopen(nocows.out, w, stdout);
     scanf(%d%d, &n, &m);
     for(j = 1; j <= m; j++){
     f[1][j] = 1;
     }
     for(j = 2; j <= m; j++){
     for(i = 1; i <= n; i += 2){
     for(k = 1; k <= i - 2; k++){
     f[i][j] += f[k][j - 1] * f[i - k - 1][j - 1];
     f[i][j] %= 9901;
     }
     }
     }
     printf(%d\\n, (9901 + f[n][m] - f[n][m - 1]) % 9901);
     return 0;
    }
  • USACO 2.3 Money Systems 货币系统 解题报告

    Money Systems

    The cows have not only created their own government but they have chosen to create their own money system. In their own rebellious way, they are curious about values of coinage. Traditionally, coins come in values like 1, 5, 10, 20 or 25, 50, and 100 units, sometimes with a 2 unit coin thrown in for good measure.

    The cows want to know how many different ways it is possible to dispense a certain amount of money using various coin systems. For instance, using a system of {1, 2, 5, 10, …} it is possible to create 18 units several different ways, including: 18×1, 9×2, 8×2+2×1, 3×5+2+1, and many others.

    Write a program to compute how many ways to construct a given amount of money using supplied coinage. It is guaranteed that the total will fit into both a signed long long (C/C++) and Int64 (Free Pascal).

    PROGRAM NAME: money
    INPUT FORMAT
    The number of coins in the system is V (1 <= V <= 25).

    The amount money to construct is N (1 <= N <= 10,000). Line 1:  Two integers, V and N 
    Lines 2..:  V integers that represent the available coins (no particular number of integers per line)


    SAMPLE INPUT (file money.in)
    3 10
    1 2 5

    OUTPUT FORMAT
    A single line containing the total number of ways to construct N money units using V coins.
    SAMPLE OUTPUT (file money.out)
    10


    描述
    母牛们不但创建了他们自己的政府而且选择了建立了自己的货币系统。由于他们特殊的思考方式,他们对货币的数值感到好奇。

    传统地,一个货币系统是由1,5,10,20 或 25,50, 和 100的单位面值组成的。

    母牛想知道有多少种不同的方法来用货币系统中的货币来构造一个确定的数值。

    举例来说, 使用一个货币系统 {1,2,5,10,…}产生 18单位面值的一些可能的方法是:18×1, 9×2, 8×2+2×1, 3×5+2+1,等等其它。写一个程序来计算有多少种方法用给定的货币系统来构造一定数量的面值。保证总数将会适合long long (C/C++) 和 Int64 (Free Pascal),即在0 到2^63-1之间。

    格式
    PROGRAM NAME: money

    INPUT FORMAT:

    (file money.in)

    货币系统中货币的种类数目是 V (1<= V<=25)。要构造的数量钱是 N (1<= N<=10,000)。

    第 1 行: 二整数,V 和 N 。

    第 2 行: 可用的货币的面值 。

    OUTPUT FORMAT:

    (file money.out)

    单独的一行包含那个可能的用这v种硬币凑足n单位货币的方案数。

    SAMPLE INPUT
    3 10
    1 2 5
    SAMPLE OUTPUT
    10

    ======================= 华丽的分割线 =======================

      看到这题就知道又是最复杂, 最有用的DP问题..(天啊!DP我怎么还没开窍?)
      dp方程:
      f[j] 代表构造价值为j的方法有多少种`?
      f[j] += f[j – c[i]]
      DP我真的不会解释,, 下次把背包九讲仔细看下!!!
      先把代码上上吧~

    /*
    LANG: C
    ID: zqy11001
    PROG: money
    */
    #include <stdio.h>
    #define getint(i) scanf(%d, &i)
    
    long long f[10001];
    
    int main(void)
    {
     int n, m;
     int i, j, k, t;
     freopen(money.in, r, stdin);
     freopen(money.out, w, stdout);
     getint(n);
     getint(m);
     f[0] = 1;
     for(i = 1; i <= n; i++){
     getint(t);
     for(j = t; j <= m; j++){
     f[j] += f[j - t];
     }
     }
     printf(%lld\\n, f[m]);
     return 0;
    }