河南省第十届ACM比赛题解

来源:互联网 发布:免费看书软件哪个好 编辑:程序博客网 时间:2024/04/30 17:28

问题 A: 谍报分析

时间限制: 1 Sec  内存限制: 128 MB

题目描述

“八一三”淞沪抗战爆发后,***几次准备去上海前线视察和指挥作战。但都因为宁沪之间的铁路和公路遭到了敌军的严密封锁,狂轰滥炸,一直未能成行。

***特科组织,其主要任务是保卫***的安全,了解和掌握敌方的动向。经过一段时间的监听,谍报组获取了敌方若干份密报,经过分析,发现密文中频繁出现一些单词,情报人员试图从单词出现的次数中,推出敌军的行动计划。

请你编程,快速统计出频率高的前十个单词。

输入

密文是由英语单词(小写字母)组成,有若干段。单词之间由一个或多个空格分开,自然段之后可以用一个“,”或“。”表示结束。整个内容的单词数量不超过10000,不同的单词个数不超过500.

输出

输出占10行,每行一个单词及出现的次数,中间一个空格。要求按频率降序输出,出现次数相同的单词,按字典序输出。

样例输入

shooting is at shanghai station. shooting  must  be carried out. shooting  shooting.shanghai station must be surrounded,  at least a team of  one hundred  soldiers to fight.  twenty  five soldiers shooting in the north, twenty  five soldiers shooting in the south,  twenty  five soldiers  shooting in  the east, twenty  five soldiers shooting in the west.

样例输出

shooting 8
soldiers 5
five 4
in 4
the 4
twenty 4
at 2
be 2
must 2
shanghai 2

提示

字符串处理的问题,有模拟成份加贪心,这里要注意的一个问题是输入如何结束。

#include<iostream>#include<math.h>#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;struct node{    string s;    int num;}a[505];int cmp(node aa,node bb){    if(aa.num==bb.num)        return aa.s<bb.s;    return aa.num>bb.num;}int main(){    for(int i=0;i<505;i++)    {        a[i].num=0;        a[i].s="";    }    char s1[1005];    int n=0;    while(scanf("%s",s1)!=EOF)    {        int i,j=0,len,flag=0;        len=strlen(s1);        string s2;        for(i=0;i<len;i++)        {            if(s1[i]!=','&&s1[i]!='.')              s2+=s1[i];        }        for(i=1;i<=n;i++)        {            if(s2==a[i].s)            {                a[i].num++;                flag=1;                break;            }        }        if(flag==0)        {            n++;            a[n].s=s2;            a[n].num++;        }    }    int i;    sort(a+1,a+1+n,cmp);    if(n>=10)    {        for(i=1; i<=10; i++)        {            //printf("%s ",a[i].s);//字符串不能用c里的printf输出            cout<<a[i].s<<" ";            printf("%d\n",a[i].num);        }    }    else    {        for(i=1; i<=n; i++)        {            cout<<a[i].s<<" ";            printf("%d\n",a[i].num);        }        for(i=n+1;i<=10;i++)            printf("\n");    }    return 0;}
   

问题 B: 情报传递

时间限制: 2 Sec  内存限制: 128 MB

题目描述

抗日战争时期,在国共合作的大背景下,中共不断发展壮大,其情报工作也开始由获取警报性、保卫性信息,向获取军政战略性情报转变。各系统情报组织遵循"荫蔽精干,长期埋伏,积蓄力量,以待时机"的隐蔽战线工作方针,开展了卓有成效的情报工作。

***特科组是中共情报工作的一个杰出范例,它以点为主、系统延伸、分散辐射的力量格局,异地领导、分头派遣、单线联系的组织形式。以打入、拉出、统战联络、内线为主的工作方式,形成了一个传递信息隐蔽、效用及时、形式多样的情报网络。

***特科组的情报人员共有N人,其代号分别为0,1,……,N-1。 0号是最高领导人,特工之间有一套严格的单线联络程序,即,每个特工人员只有一个上线,他获得的情报需层层上传递到0号手里,由0号发报出去。

特工i在传递情报时,若通往到0号的通道尚未建立,则需要建立一级级单线通道;若他的上线已建立好通道,只需建立两人通道,信息发送给上线;依次类推。若特工i已建立好到0号的通道,则直接发出情报。日伪统治中心南京,既是情报来源丰富的地方,又是特工人员活动最危险的地方。因此,一旦某个特工处于不安全状态,他必须马上撤离,同时他的所有下线(处在通道上的一级级下线)也一同撤离。

已知***特科组的组织结构,你的任务是计算,当某特工i需要发送情报时,最少需要建立几个情报人员的通道;当某特工i处于不安全状态时,最少需要撤离多少人员。

输入

第一行一个整数:  N           ( 1≤N ≤5060 )

接下来一行有N-1 个整数,  A1 A2 ……An-1  ,其中Ai是编号i的上线。

下一行一个整数:  M         表示有M个状态,( 1≤M ≤5060 )

接下来有M行 :有两种形式:  Send i    特工i处于要发送情报状态;

                             Danger i  特工i处于不安全状态

输出

输出占M行 ,对于Send i,输出最少需要建立通道的情报人员数,若特工i处于通道线上,输出0;对于Danger i,输出最少需要撤离多少人员,若特工i不处于通道线上,则输出0.

样例输入

10
0 1 2 1 3 0 0 3 2
10
Send 0
Send 3
Danger 2
Send 7
Send 5
Send 9
Danger 9
Send 4
Send 1
Send 9

样例输出

1
3
2
1
3
1
1
1
0
1

提示

模拟可做,这个题就是说首先给你情报关系网,但是在开始的时候这个关系网并没有建立,你只是知道他们的上下级关系。

然后再通过Send和Danger这两种操作来真正建立关系,要注意的是虽然0是最高领导人但他要发出情报也是要和别人建立一条通道的。

在输入的时候,(由于每个人只对应一个上线)我把每个人对应的上线保存下来,在建立关系的时候就一直向前回溯一直到0,中途如果有没有建立关系的地方则需建立的通道数就加1。对于判断一个点有没有在通道内,我是用了一个变量来存储这个点的状态(0表示在通道内,1表示不在通道内)

再接着就是对于Danger的处理了,那么就需要知道所涉及到的点的下线了,这里我就用到了动态数组vector,用递归的方法将当前需撤离点之后的在通道内的数量记录下来并将状态改变。

#include<iostream>#include<math.h>#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>using namespace std;int num;struct node{    int y;//表示当前点的状态 1为不在通道状态 0为在通道状态    int x;//表示当前点的上线}b[10005];vector<int>s[5070];int danger(int d){    if(b[d].y==0)    {        b[d].y=1;        num+=b[d].y;    }    for(int i=0; i<s[d].size(); i++)    {        //num+=s[s[d][i]].size();        danger(s[d][i]);    }}int main(){    int n,m,a[5070],i,j;    scanf("%d",&n);    for(i=1;i<n;i++)    {        scanf("%d",&a[i]);        b[i].x=a[i];//保存上线        s[a[i]].push_back(i);//保存下线    }    b[0].x=-1;//0把情报发出去也要建立通道    for(i=0;i<n;i++)        b[i].y=1;//初始状态不在通道内    scanf("%d",&m);    char str[10];    int d,pre,post,flag=0;    while(m--)    {        scanf("%s",str);        scanf("%d",&d);        if(d==0)            flag=0;        pre=d,num=0,post=d;        if(str[0]=='S')        {            while(pre!=-1)            {                num+=b[pre].y;                b[pre].y=0;                pre=b[pre].x;            }            printf("%d\n",num);        }//建立关系        else        {            if(b[d].y==1)                printf("0\n");            else            {                danger(d);                printf("%d\n",num);            }        }//撤离关系    }    return 0;}

问题 C: 最小秘钥

时间限制: 1 Sec  内存限制: 128 MB

题目描述

在中国近代史上,暂编***军绝对是一支能打硬仗,大名鼎鼎的行动部队。“一二八”上海抗战,暂编***军就曾打得小日本四易主帅。

*月**号,暂编***军计划组成一个行动大队,派出N名队员潜伏在***地,发动一次大规模的巷战行动。每名队员有自己的代号Ai,为了更好的配合作战,他们需要获得一个密钥Key,  然后各自迅速移动到Ai  MOD  Key位置,**时刻一起开战。

作战方案已经定好,你能帮***行动大队快速找个满足条件的最小密钥Key吗?

MOD表示取模运算,要求不能有多名队员待在同一个位置。

输入

第一行: T        表示以下有T组测试数据             ( 1≤T ≤5 )

对每组数据,  

第一行:N     表示行动人员数  (1<=N<=3000)

接下来一行有N个整数,分别表示每个队员的代号Ai       (1<=Ai<=20000)

输出

对每组测试数据,输出占一行,一个整数 Key.  

样例输入

2
3
1 2 3
5
4 6 9 10 13

样例输出

3
8

提示

这题就没什么好说的了

#include<iostream>#include<math.h>#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n,i,j,a[3005],b[20005],flag;        scanf("%d",&n);        for(i=0;i<n;i++)            scanf("%d",&a[i]);        i=2;        while(1)        {            flag=0;            memset(b,0,sizeof(b));            for(j=0; j<n; j++)            {                if(b[a[j]%i]==1)                {                    flag=1;                    break;                }                b[a[j]%i]=1;            }            if(flag==0)                break;            i++;        }        printf("%d\n",i);    }    return 0;}

问题 D: 年终奖金

时间限制: 2 Sec  内存限制: 128 MB

题目描述

***公司承接了N个项目需要年底完成,每个项目有一定的难度系数。由于项目太多了,需要招聘大量的技术人员。要求每个技术人员至少完成K个项目。

考虑到有些项目之间相似性以及项目的难易程度,为了避免某些员工只挑选轻松项目,CEO提出了一个奖励机制,当技术人员完成分配给他的任务后,年终可以得到一笔奖金,其得到的酬金将是C + (Tmax–Tmin)2。其中,Tmax表示所做项目的最大的难度系数,Tmin是难度系数的最小值。

你能否计算一下,为了完成所有项目,***公司年终至少需要支付多少酬金?

输入

输入有多组测试数据。对每组测试数据:

        第一行: N  K  C     (1<=N,K<=100   1<=C<=5000 )

        第二行   N个正整数分别描述N个项目的难度系数。(1<=难度系数<=10000)

输出

对每组测试数据:输出占一行,一个整数。即,***公司年终至少需要支付的酬金数。

样例输入

2 1 1
2 4
10 2 3
1 4 10 3 10 1 8 3 8 3

样例输出

2
13

提示

第一组测试数据,如果一个人完成,酬金为1 + (4–2)2 = 5;如果分给两个人去完成,收费为1 + 1 = 2。

思路:这是一道DP题,很多人一开始都会觉得是贪心问题

最后要求出最小值,初始化为最大值且b[0]=0;

题目要求每个人至少做k个项目(这是一个约束条件),求最少需付?

#include<bits/stdc++.h>#define INF 0x3f3f3f3fusing namespace std;int a[150];int b[150];int main(){    int N,K,C;    while(~scanf("%d%d%d",&N,&K,&C)){    memset(b,INF,sizeof(b));    for(int i=1;i<=N;i++)        scanf("%d",&a[i]);    sort(a+1,a+1+N);    b[0]=0;    for(int i=K;i<=N;i++)    {        for(int j=1;j<=i;j++)        {            if(i-j+1<K)                continue;            else                b[i]=min(b[i],b[j-1]+(a[i]-a[j])*(a[i]-a[j])+C);        }    }    printf("%d\n",b[N]);    }    return 0;}

问题 F: Binary to Prime

时间限制: 1 Sec  内存限制: 128 MB

题目描述

To facilitate the analysis of  a DNA sequence,  a DNA sequence is represented by a binary  number. The group of  DNA-1 has discovered a great new way .  There is a certain correlation between binary number and prime number. Instead of using the ordinary decadic numbers, they use prime base numbers. Numbers in this base are expressed as sequences of zeros and ones similarly to the binary numbers, but the weights of bits  in the representation are not powers of two, but the elements of the primes  ( 2, 3, 5, 7,... ).

 

For example  01101 , ie. 2+5+7=14

 

Herefore, it is necessary to convert the binary number to the sum of prime numbers 

输入

The input consists of several instances, each of them consisting of a single line. Each line of the input contains a 01 string, length of not more than 150.  The end of input is not marked in any special way.

输出

For each test case generate a single line containing a single integer , The sum of the primes.

样例输入

000010
0011
11001

样例输出

3
5
20

提示

概括来说就是素数权重(不同于以往的二进制权重),数据也不大,找出前150个素数就可以了

#include<iostream>#include<math.h>#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int b[155];int prime(int n){    int i;    if(n==0||n==1)        return -1;    if(n==2||n==3)        return 1;    for(i=2;i<=sqrt(n);i++)    {        if(n%i==0)            return -1;//不是    }    return 1;}int main(){    int k,kk=0,i;    for(k=0;k<1000;k++)    {        if(prime(k)==1)           b[kk++]=k;    }    /*for(i=0;i<kk;i++)        printf("%d ",b[i]);    printf("\n%d ",kk);*/    char a[155];    while(scanf("%s",a)!=EOF)    {        int i,j,len;        long long int s=0;        len=strlen(a);        for(i=len-1;i>=0;i--)            s+=(a[i]-'0')*b[len-1-i];        printf("%lld\n",s);    }    return 0;}

问题 G: Plumbing the depth of lake

时间限制: 1 Sec  内存限制: 128 MB

题目描述

There is a mysterious lake in the north of Tibet. As the sun shines, the surface of the lake is colorful and colorful. The lake was unfathomable in rainy weather.  After the probe,  It has an interesting bottom in that it is full of little hills and valleys. . Scientists wonders how deep the bottom of the lake is.

 

Scientists use the most advanced radar equipment to detect the bottom of the lake. It is the discovery that the deepest part is relatively flat. Thet want to know the largest depth number only if it is verified by the fact that the same depth appears in an adjacent reading.

 

To facilitate computing, scientists have put the lake as M * N grids . The depth  reading of each grid is already known. some readings might be 0-- It's a small island on the lake.

 

Find the greatest depth that appears in at least two 'adjacent'readings (where 'adjacent' means in any of the potentially eight squares that border a square on each of its sides and its diagonals). The lake has at least one pair of positive, adjacent readings.

输入

The first line of the input contains one integers T, which is the nember of  test cases (1<=T<=5).  Each test case specifies:

 

* Line 1:      Two space-separated integers: M and N   (1 ≤ M,  N ≤ 50)

* Lines 2..M+1: Line i+1 contains N space-separated integers that  represent the depth of the lake across row i: Dij    (0 <= Dij <=1,000,000);

输出

For each test case generate a single line:  a single integer that is the depth of the lake determined.

样例输入

1
4 3
0 1 0
1 2 0
1 5 1
2 3 4

样例输出

1

提示

这道题有点坑的是题目简单的我不敢相信,翻译完之后我就觉得啊应该不这么简单,归根结底还是我个人的原因,我改。
#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;int dir[8][2]={{-1,0},{1,0},{0,-1},{0,1},{-1,-1},{-1,1},{1,-1},{1,1}};int main(){    int t;    scanf("%d",&t);    while(t--)    {        int i,j,m,n,max=0,k;        int a[55][55];        scanf("%d %d",&m,&n);        for(i=0;i<m;i++)            for(j=0;j<n;j++)            scanf("%d",&a[i][j]);        for(i=0;i<m;i++)            for(j=0;j<n;j++)        {            for(k=0;k<8;k++)            if(a[i][j]==a[i+dir[k][0]][j+dir[k][1]]&&a[i][j]>max&&i+dir[k][0]>=0&&i+dir[k][0]<m&&j+dir[k][1]>0&&j+dir[k][1]<n)               max=a[i][j];        }        printf("%d\n",max);    }    return 0;} 

有8个可以搜的方向,必须周围有一个和其一样的才可以被考虑在内。在这个情况下请输出一个最大的数(此数代表湖的深度)

问题 H: Intelligent Parking Building

时间限制: 1 Sec  内存限制: 128 MB

题目描述

There is a new revolution in the parking lot business: the parking  building. The concept is simple: you drive your car into the elevator at the entrance of the building, and the elevator and conveyor belts drag the car to an empty parking spot, where the car remains until you pick it up. When you return, the elevator and conveyor belts move your car back to the entrance and you’re done.

The layout of the building is simple. There is one central elevator that transports the cars between the different floors. On each floor there is one giant circular conveyor belt on which the cars stand. This belt can move in clockwise and counterclockwise direction. When the elevator arrives on a floor, it becomes part of the belt so that cars can move through it.

At the end of the day the building is usually packed with cars and a lot of people come to pick them up. Customers are processed in a first come first serve order: the elevator is moved to the floor of the first car, the conveyor belt moves the car on the elevator, the elevator is moved down again, and so on. We like to know how long it takes before the last customer gets his car. Moving the elevator one floor up- or downwards takes 10 seconds and moving  the conveyor belt one position in either direction takes 5 seconds. 

输入

On the first line one positive number: the number of testcases, at most 30.  Each test case specifies:

  • One line with two integers h and l with 1 ≤ h ≤ 50 and 2 ≤ l ≤ 50: the height of the parking tower and the length of the conveyor belts.
  • h lines with l integers: the initial placement of the cars. The jth number on the ith line describes the jth position on the ith floor. This number is −1 if the position is empty, and r if the position is occupied by the rth car to pick up. The positive numbers form a consecutive sequence from 1 to the number of cars. The entrance is on the first floor and the elevator (which is initially empty) is in the first position. There is at least one car in the parking tower.

输出

For each test case generate a single line containing a single integer  that is the number of seconds before the last customer is served.

 

样例输入

3
1  5
1  -1  -1  -1  2 
1  5
2  -1  -1  -1  1 
3 6
-1  5  6  -1  -1  3
-1  -1  7  -1  2  9
-1  10  4  1  8  -1

样例输出

5
10
320

提示

这也是一道很坑的翻译啊,很多人就卡在不懂题意这了。这也只能怪我平常英语没学好。

纯模拟,大一做的简单模拟题电梯的升级版。上下电梯的时间当然容易算,就是每次传送带转动的时候,将需要提走的车转到指定位置之后,序列需要更新一下而已。

#include<iostream>#include<math.h>#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;struct point{    int x;    int y;} b[2505];int min(int x,int y){    if(x>y)        return y;    return x;}int max(int x,int y){    if(x>y)        return x;    return y;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int m,n,i,j,maxn=0,s=0,minn,len1;        int a[55][55],aa[55];        scanf("%d %d",&n,&m);        for(i=0; i<n; i++)            for(j=0; j<m; j++)            {                scanf("%d",&a[i][j]);                if(maxn<a[i][j])                    maxn=a[i][j];            }        for(i=0; i<n; i++)            for(j=0; j<m; j++)            {                if(a[i][j]!=-1)                {                    b[a[i][j]].x=i;                    b[a[i][j]].y=j;                }            }        for(i=1; i<=maxn; i++)            s+=2*10*b[i].x;        for(i=1; i<=maxn; i++)        {            minn=min(b[i].y,m-b[i].y)*5;            s+=minn;            len1=b[i].y;            for(j=0; j<m-b[i].y; j++)            {                aa[j]=a[b[i].x][len1];                len1++;            }            len1=0;            for(j=m-b[i].y; j<m; j++)            {                aa[j]=a[b[i].x][len1];                len1++;            }            for(j=0; j<m; j++)            {                a[b[i].x][j]=aa[j];                if(aa[j]!=-1)                    b[aa[j]].y=j;            }        }        printf("%d\n",s);    }    return 0;}
小结:多刷题,多翻译,持之以恒







原创粉丝点击