[HDU]ACM Steps-Chapter One-Section 3

来源:互联网 发布:佳能mg3680清零软件 编辑:程序博客网 时间:2024/05/16 05:50
1.3.1
Problem Description
The famous ACM (Advanced Computer Maker) Company has rented a floor of a building whose shape is in the following figure. 



The floor has 200 rooms each on the north side and south side along the corridor. Recently the Company made a plan to reform its system. The reform includes moving a lot of tables between rooms. Because the corridor is narrow and all the tables are big, only one table can pass through the corridor. Some plan is needed to make the moving efficient. The manager figured out the following plan: Moving a table from a room to another room can be done within 10 minutes. When moving a table from room i to room j, the part of the corridor between the front of room i and the front of room j is used. So, during each 10 minutes, several moving between two rooms not sharing the same part of the corridor will be done simultaneously. To make it clear the manager illustrated the possible cases and impossible cases of simultaneous moving. 



For each room, at most one table will be either moved in or moved out. Now, the manager seeks out a method to minimize the time to move all the tables. Your job is to write a program to solve the manager’s problem.
 

Input
The input consists of T test cases. The number of test cases ) (T is given in the first line of the input. Each test case begins with a line containing an integer N , 1<=N<=200 , that represents the number of tables to move. Each of the following N lines contains two positive integers s and t, representing that a table is to move from room number s to room number t (each room number appears at most once in the N lines). From the N+3-rd line, the remaining test cases are listed in the same manner as above.
 

Output
The output should contain the minimum time in minutes to complete the moving, one per line.
 

Sample Input
3 4 10 20 30 40 50 60 70 80 2 1 3 2 200 3 10 100 20 80 30 50 
 

Sample Output
102030
巧妙地题型。贪心算法,预处理打表,建一个0的表来表示两个间的走廊,每用一次加一,多一个则表示时间多一个十分钟。
#include<stdio.h>
#include<string.h>
int save[205];
int main()
{
    int m;
    scanf("%d", &m);
    while (m--)
    {
        int n;
        scanf("%d", &n);
        memset(save, 0, sizeof(save));
        int a, b;
        int tem1, tem2;
        int i;
        while (n--)
        {
            scanf("%d %d", &tem1, &tem2);
            if (tem1 < tem2) { a = tem1, b = tem2; }
            else { a = tem2, b = tem1; }
            a = (a + 1) / 2;
            b = (b + 1) / 2;
            if (a == b)save[a]++;
            else for (i = a; i <= b; i++)
                save[i]++;
        }
        int max = 0;
        for (i = 1; i <= 200; i++)
            if (max < save[i])max = save[i];
        printf("%d\n", max * 10);
    }
    return 0;
}

1.3.2
Problem Description
“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
“@#$%^&*%...”

确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。
作 为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、 超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)
 

Input
输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据 Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。
 

Output
对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。
 

Sample Input
121 33 40 73 815 1915 2010 158 186 125 104 142 90
 

Sample Output
5
#include<stdio.h>
#include<string.h>
int save[100][2];
int k[100];
int main()
{
    int n;
    while (scanf("%d", &n) && n != 0)
    {
        int i;
        for (i = 0; i < n; i++)
            scanf("%d %d", &save[i][0], &save[i][1]);
        int x, y, tem;
        int sum = 0;
        for (x = 0; x < n - 1; x++)
            for (y = 0; y < n - x - 1; y++)
                if (save[y][1] - save[y][0]>save[y + 1][1] - save[y + 1][0])
                {
                    tem = save[y][0];
                    save[y][0] = save[y + 1][0];
                    save[y + 1][0] = tem;
                    tem = save[y][1];
                    save[y][1] = save[y + 1][1];
                    save[y + 1][1] = tem;
                }

        for (y = 0; y < n; y++)
        {
                int w = 0;
                for (x = save[y][0]+1; x <= save[y][1]-1; x++)
                {
                    if (k[x] != 0) { w = 1; break; }
                }
                if (w == 0) 
                {
                    sum++;                
                    for (x = save[y][0]; x <= save[y][1]; x++)
                    {
                        k[x] = 1;
                    }
                }
        }
        printf("%d\n", sum);
    }
    return 0;
}

1.3.3
Problem Description
Here is a famous story in Chinese history.

"That was about 2300 years ago. General Tian Ji was a high official in the country Qi. He likes to play horse racing with the king and others."

"Both of Tian and the king have three horses in different classes, namely, regular, plus, and super. The rule is to have three rounds in a match; each of the horses must be used in one round. The winner of a single round takes two hundred silver dollars from the loser."

"Being the most powerful man in the country, the king has so nice horses that in each class his horse is better than Tian's. As a result, each time the king takes six hundred silver dollars from Tian."

"Tian Ji was not happy about that, until he met Sun Bin, one of the most famous generals in Chinese history. Using a little trick due to Sun, Tian Ji brought home two hundred silver dollars and such a grace in the next match."

"It was a rather simple trick. Using his regular class horse race against the super class from the king, they will certainly lose that round. But then his plus beat the king's regular, and his super beat the king's plus. What a simple trick. And how do you think of Tian Ji, the high ranked official in China?"



Were Tian Ji lives in nowadays, he will certainly laugh at himself. Even more, were he sitting in the ACM contest right now, he may discover that the horse racing problem can be simply viewed as finding the maximum matching in a bipartite graph. Draw Tian's horses on one side, and the king's horses on the other. Whenever one of Tian's horses can beat one from the king, we draw an edge between them, meaning we wish to establish this pair. Then, the problem of winning as many rounds as possible is just to find the maximum matching in this graph. If there are ties, the problem becomes more complicated, he needs to assign weights 0, 1, or -1 to all the possible edges, and find a maximum weighted perfect matching...

However, the horse racing problem is a very special case of bipartite matching. The graph is decided by the speed of the horses --- a vertex of higher speed always beat a vertex of lower speed. In this case, the weighted bipartite matching algorithm is a too advanced tool to deal with the problem.

In this problem, you are asked to write a program to solve this special case of matching problem.
 

Input
The input consists of up to 50 test cases. Each case starts with a positive integer n (n <= 1000) on the first line, which is the number of horses on each side. The next n integers on the second line are the speeds of Tian’s horses. Then the next n integers on the third line are the speeds of the king’s horses. The input ends with a line that has a single 0 after the last test case.
 

Output
For each input case, output a line containing a single number, which is the maximum money Tian Ji will get, in silver dollars.
 

Sample Input
392 83 7195 87 74220 2020 20220 1922 180
 

Sample Output
20000

贪心算法
1,如果田忌的最快马快于齐王的最快马,则两者比。(因为若是田忌的别的马很可能就赢不了了,所以两者比)2,如果田忌的最快马慢于齐王的最快马,则用田忌的最慢马和齐王的最快马比。(由于所有的马都赢不了齐王的最快马,所以用损失最小的,拿最慢的和他比)3,若相等,则比较田忌的最慢马和齐王的最慢马3.1,若田忌最慢马快于齐王最慢马,两者比。(田忌的最慢马既然能赢一个就赢呗,而且齐王的最慢马肯定也得有个和他比,所以选最小的比他快得。)3.2,其他,则拿田忌的最慢马和齐王的最快马比。(有三种可能,齐王最快和田忌最慢一样速度+0以及齐王最快比田忌最慢快-1)(反正所有的马都比田忌的最慢马快了,所以这匹马必输,选贡献最大的,干掉齐王的最快马)
注意:用cont在比较时计数,因为一共就sum匹马,所以比cont次,更加方便且不容易出错!
#include<stdio.h>
int main()
{
    int sum, i;
    while (scanf("%d", &sum) && sum != 0)
    {
        int my[1005];
        int you[1005];
        for (i = 0; i < sum; i++)scanf("%d", &my[i]);
        for (i = 0; i < sum; i++)scanf("%d", &you[i]);
        int tem;
        int x, y;
        for (x = 0; x < sum - 1; x++)
            for (y = 0; y < sum - x - 1; y++)
            {
                if (my[y + 1]>my[y])
                {
                    tem = my[y + 1];
                    my[y + 1] = my[y];
                    my[y] = tem;
                }
                if (you[y + 1]>you[y])
                {
                    tem = you[y + 1];
                    you[y + 1] = you[y];
                    you[y] = tem;
                }
            }
        int ma = 0, mb = sum - 1, ya = 0, yb = sum - 1, res = 0;
        int cont = 0;
        while ((cont++) < sum)
        {
            if (my[ma] > you[ya]) { res++; ya++; ma++; }
            else if (my[ma] < you[ya]) { res--; mb--; ya++; }
            else
            {
                if (my[mb] > you[yb]) { res++; yb--; mb--; }
                else
                {
                    if (my[mb] < you[ya]) { res--; }
                    mb--; ya++;
                }
            }
        }
        printf("%d\n", res * 200);
    }
}

1.3.4
Problem Description
时维九月,序属三秋,辽军大举进攻MCA山,战场上两军正交锋.辽军统帅是名噪一时的耶律-James,而MCA方则是派出了传统武将中草药123.双方 经过协商,约定在十一月八日正午十分进行射箭对攻战.中草药123早早就开始准备,但是他是武将而不是铁匠,造弓箭的活就交给聪明能干的你了,现在告诉你 每种弓箭规格,即箭身的长度,以及每种规格弓箭所需要的数目,要求你把需要的弓箭都输出.
弓箭的基本样子为 ">+---+>",其中"+---+"为箭身,数据保证箭身长度 > 2
 

Input
首先输入一个t,表示有t组数据,跟着t行:
每行一个N (N < 50 ),接下去有N行,第i行两个整数Ai , Bi,分别代表需要箭身长度为Ai的弓箭Bi枝. (Ai < 30 , Bi < 10 )
输入数据保证每一个Ai都是不同的.
 

Output
按照箭身的长度从小到大的顺序依次输出所有需要的弓箭,"每一种"弓箭后输出一个空行.
 

Sample Input
143 44 55 66 7
 

Sample Output
>+-+>>+-+>>+-+>>+-+>>+--+>>+--+>>+--+>>+--+>>+--+>>+---+>>+---+>>+---+>>+---+>>+---+>>+---+>>+----+>>+----+>>+----+>>+----+>>+----+>>+----+>>+----+>
 
这一题有一些表述不清,注意要在每一个大组内进行排序!
#include <stdio.h>
int save[60][2];
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        int n;
        scanf("%d", &n);
        int i;
        for (i = 0; i < n; ++i)
        {
            scanf("%d %d", &save[i][0], &save[i][1]);
        }
        int tem, x, y;
        for (x = 0; x < n - 1; x++)
            for (y = 0; y < n - x - 1; y++)
                if (save[y + 1][0] < save[y][0])
                {
                    tem = save[y][0];
                    save[y][0] = save[y + 1][0];
                    save[y + 1][0] = tem;
                    tem = save[y][1];
                    save[y][1] = save[y + 1][1];
                    save[y + 1][1] = tem;
                }
        for (i = 0; i < n; i++)
        {
            char key[50];
            key[0] = '>';
            key[1] = '+';
            int w;
            for (w = 2; w < save[i][0]; w++)
                key[w] = '-';
            key[w] = '+';
            key[w + 1] = '>';
            key[w + 2] = '\0';
            for (w = 0; w < save[i][1]; w++)
                puts(key);
            printf("\n");
        }
    }
    return 0;
}

1.3.5
Problem Description
每天第一个到机房的人要把门打开,最后一个离开的人要把门关好。现有一堆杂乱的机房签 
到、签离记录,请根据记录找出当天开门和关门的人。 
 

Input
测试输入的第一行给出记录的总天数N ( > 0 )。下面列出了N天的记录。 
每天的记录在第一行给出记录的条目数M ( > 0 ),下面是M行,每行的格式为 

证件号码 签到时间 签离时间 

其中时间按“小时:分钟:秒钟”(各占2位)给出,证件号码是长度不超过15的字符串。
 

Output
对每一天的记录输出1行,即当天开门和关门人的证件号码,中间用1空格分隔。 
注意:在裁判的标准测试输入中,所有记录保证完整,每个人的签到时间在签离时间之前, 
且没有多人同时签到或者签离的情况。 
 

Sample Input
31ME3021112225321 00:00:00 23:59:592EE301218 08:05:35 20:56:35MA301134 12:35:45 21:40:423CS301111 15:30:28 17:00:10SC3021234 08:00:00 11:25:25CS301133 21:45:00 21:58:40
 

Sample Output
ME3021112225321 ME3021112225321EE301218 MA301134SC3021234 CS301133
 
#include <stdio.h>
#include <string.h>
typedef struct MyStruct
{
    int hour;
    int min;
    int sen;
}save;
int main()
{
    int n;
    scanf("%d", &n);
    while (n--)
    {
        int m;
        scanf("%d", &m);
        save in;
        save out;
        int i = 0;
        int max, min, tem1, tem2;
        char namemax[20];
        char namemin[20];
        char name[20];
        while (m--)
        {
            scanf("%s %2d:%2d:%2d %2d:%2d:%2d", name, &in.hour, &in.min, &in.sen, &out.hour, &out.min, &out.sen);
            tem1 = in.hour * 3600 + in.min * 60 + in.sen;
            tem2 = out.hour * 3600 + out.min * 60 + out.sen;
            if (i == 0)
            {
                strcpy(namemax, name);
                strcpy(namemin, name);
                max = tem2;
                min = tem1;
                i = 1;
            }
            if (tem2 > max)
            {
                strcpy(namemax, name);
                max = tem2;
            }
            if (tem1 < min)
            {
                strcpy(namemin, name);
                min = tem1;
            }
        }
        printf("%s %s\n", namemin, namemax);
    }
    return 0;
}

1.3.6
Problem Description
话说上回讲到海东集团面临内外交困,公司的元老也只剩下XHD夫妇二人了。显然,作为多年拼搏的商人,XHD不会坐以待毙的。
  一 天,当他正在苦思冥想解困良策的时候,突然想到了自己的传家宝,那是公司成立的时候,父亲作为贺礼送来的一个锦囊,徐父当时交代,不到万不得已的时候,不 要打开它。“现在不正是最需要的时候吗?”,一边想,XHD一边找到了这个精心保管的锦囊,打开一看,里面只有一句话“杭城北麓千人洞有宝”。
  二话不说,XHD拿起一个大口袋就出发了,这个千人洞他是知道的,小的时候,爸爸曾经带他来过这个隐蔽的路口,并告诉他,这是千人洞。他现在才明白爸爸当初这句话的含义。
  尽 管有点印象,XHD还是花了很大的精力才找到这个异常隐蔽的洞口,走进一看,几乎惊呆了,真的是眼花缭乱!不过尽管宝贝的种类不少,但是每种宝贝的量并不 多,当然,每种宝贝单位体积的价格也不一样,为了挽救HDU,现在请你帮忙尽快计算出来XHD最多能带回多少价值的宝贝?(假设宝贝可以分割,分割后的价 值和对应的体积成正比)
 

Input
输入包含多个测试实例,每个实例的第一行是两个整数v和n(v,n<100),分别表示口袋的容量和宝贝的种类,接着的n行每行包含2个整数pi和 mi(0<pi,mi<10),分别表示某种宝贝的单价和对应的体积,v为0的时候结束输入。
 

Output
对于每个测试实例,请输出XHD最多能取回多少价值的宝贝,每个实例的输出占一行。
 

Sample Input
2 23 12 30
 

Sample Output
5经过锦囊相助,HDU会脱离危机吗?欲知后事如何,且听下回分解——
 
#include <stdio.h>
int main()
{
    int bagsum,n;
    while (scanf("%d %d", &bagsum, &n) && bagsum != 0)
    {
        int save[100][2];
        int a, b, i=0,tem;
        while (i<n)
        {
            scanf("%d %d", &save[i][0], &save[i][1]);
                i++;
        }
        for (a = 0; a < n - 1; a++)
            for (b = 0; b < n - a - 1; b++)
            {
                if (save[b][0] < save[b + 1][0])
                {
                    tem = save[b][0];
                    save[b][0] = save[b + 1][0];
                    save[b + 1][0] = tem;
                    tem = save[b][1];
                    save[b][1] = save[b + 1][1];
                    save[b + 1][1] = tem;
                }
            }
        int sum=0,pr=0,sumi=0;
        for (i = 0; i < n;)
        {
            if (save[i][1] == 0) { i++; continue; }
            if (sumi + 1 <= bagsum) { sum += save[i][0]; sumi++; save[i][1]--; }
            else break;    
        }
        printf("%d\n", sum);
    }
    return 0;
}


1.3.7
Problem Description
在上一回,我们让你猜测海东集团用地的形状,你猜对了吗?不管结果如何,都没关系,下面我继续向大家讲解海东集团的发展情况:
在最 初的两年里,HDU发展非常迅速,综合各种ACM算法生成的老鼠药效果奇好,据说该药专对老鼠有效,如果被人误食了,没有任何副作用,甚至有传闻说还有健 胃的效果,不过这倒没有得到临床验证。所以,公司的销量逐年递增,利润也是节节攀升,作为股东之一的公主负责财务,最近半年,她实在辛苦,多次因为点钞票 造成双手抽筋而住院,现在在她面前你根本不要提到“钞票”二字,甚至“money”也不行,否则她立马双手抽筋,唉,可怜的公主…
海东集团的发展令国人大为振奋,不过也引起了邻国同行业“东洋小苟株式会社”的嫉妒,眼看海东集团逐渐把他们原来的市场一一占领,心中自是不甘,于是派了n个人前来挑衅,提出要来一场比试真功夫的中日擂台赛,输的一方要自动退出老鼠药市场!
他们提出的比赛规则是这样的:
1.  每方派出n个人参赛;
2.  出赛的顺序必须是从弱到强(主要担心中国人擅长的田忌赛马);
3.  每赢一场,得两分,打平得一分,否则得0分。
东洋小苟果然够黑,不过他们万万没有想到,HDU可是卧虎藏龙,不仅有动若脱兔的Linle,还有力大如牛的伪**,更有下沙健美先生HeYing以及因为双手抽筋而练成鹰爪功的月亮公主,估计小苟他们也占不到什么便宜。
假设每个队员的能力用一个整数来表示,你能告诉我最终的结果吗?
 

Input
输入包含多组测试数据,每组数据占3行,首先一行是一个整数n(n<100),表示每方上场队员的人数,接着的二行每行包含n个整数,分别依次表示中日两方人员的能力值,n为0的时候结束输入。
 

Output
对于每个测试实例,请输出比赛的结果,结果的格式如样例所示(数字和vs之间有且仅有一个空格),其中,HDU的比分在前。
每个实例的输出占一行。
 

Sample Input
35 2 61 3 40
 

Sample Output
6 vs 0这次的擂台赛,HDU能赢吗?欲知后事如何,且听下回分解——
 
#include<stdio.h>
int main()
{
    int a[110], b[110];
    int sum;
    while (scanf("%d", &sum)&&sum)
    {
        int suma = 0;
        int sumb = 0;
        int i;
        for (i = 0; i < sum; i++)
            scanf("%d", &a[i]);
        for (i = 0; i < sum; i++)
            scanf("%d", &b[i]);
        int x, y;
        for (x = 0; x < sum - 1; x++)
            for (y = 0; y < sum - 1 - x; y++)
            {
                int tem;
                if (a[y] > a[y + 1])
                {
                    tem = a[y];
                    a[y] = a[y + 1];
                    a[y + 1] = tem;
                }
                if (b[y] > b[y + 1])
                {
                    tem = b[y];
                    b[y] = b[y + 1];
                    b[y + 1] = tem;
                }
            }
        for (i = 0; i < sum; i++)
        {
            if (a[i] > b[i])
                suma += 2;
            else if (a[i] == b[i])
            {
                suma++; sumb++;
            }
            else sumb += 2;
        }
        printf("%d vs %d\n", suma, sumb);
    }
    return 0;
}

1.3.8
Problem Description
Jackson wants to know his rank in the class. The professor has posted a list of student numbers and marks. Compute Jackson’s rank in class; that is, if he has the top mark(or is tied for the top mark) his rank is 1; if he has the second best mark(or is tied) his rank is 2, and so on.
 

Input
The input consist of several test cases. Each case begins with the student number of Jackson, an integer between 10000000 and 99999999. Following the student number are several lines, each containing a student number between 10000000 and 99999999 and a mark between 0 and 100. A line with a student number and mark of 0 terminates each test case. There are no more than 1000 students in the class, and each has a unique student number.
 

Output
For each test case, output a line giving Jackson’s rank in the class.
 

Sample Input
2007010120070102 10020070101 3320070103 2220070106 330 0
 

Sample Output
2
这题一定要注意最外层是一个大while循环!然后以!=EOF然后以标志结束
#include<stdio.h>
int main()
{
    int savename;
    while(scanf("%d",&savename)!=EOF)
    {
        int i=0;
        int savenum;
        int a,b,k=0;
        int save[1010][2];
        while(1)
        {
            scanf("%d %d",&a,&b);
            if(a==0||b==0)break;
            save[i][0]=a;
            save[i][1]=b;
            if(a==savename)savenum=b;
            i++;
        }
        int tem,x,y;
        int sum=i,res=1;
        for(x=0; x<sum-1; x++)
            for(y=0; y<sum-x-1; y++)
            {
                if(save[y+1][1]>save[y][1])
                {
                    tem=save[y+1][1];
                    save[y+1][1]=save[y][1];
                    save[y][1]=tem;
                    tem=save[y+1][0];
                    save[y+1][0]=save[y][0];
                    save[y][0]=tem;
                }
            }
        for(i=0; i<sum; i++)
            if(save[i][1]>savenum)res++;
            else if(save[i][1]<savenum)break;
        printf("%d\n",res);
    }
    return 0;
}
0 0
原创粉丝点击