湖南省第十一届大学生计算机程序设计竞赛 A,B,C,D,F,H,J 题解

先贴上,代码吃完饭回来补偷笑, 吃饭为大.

A: Aerial Tramway

时间限制: 1 Sec  内存限制: 128 MB
提交: 0  解决: 0
[提交][状态][讨论版]

题目描述

An aerial tramway, cable car, ropeway or aerial tram is a type of aerial lift which uses one or two stationary ropes for support while a third moving rope provides propulsion. With this form of lift, the grip of an aerial tramway cabin is fixed onto the propulsion rope and cannot be decoupled from it during operations.
 -- Wikipedia


You own a park located on a mountain, which can be described as a sequence of n points (xi, yi) from left to right, where xi,yi>0, xii+1, yi!=yi+1 (that means there will not be horizontal segments in the mountain skyline), illustrated below(the numbers are the corresponding x-coordinate):

Since the mountain is very sloppy, some aerial tramways across the park would be very helpful. In the figure above, people can go from p4 to p9 directly, by taking a tram. Otherwise he must follow a rather zigzag path: p4-p5-p6-p7-p8-p9.
Your job is to design an aerial tramway system. There should be exactly m trams, each following a horizontal segment in the air, between two points pi and pj. "Horizontal" means yi=yj, “in the air" means all the points in between are strictly below, i.e. yki for every i2 and p9, because p4 is not strictly below p2-p9. However, you can have two trams, one from p2 to p4, and one p4 to p9. There is another important restriction: no point can be strictly below k or more tramways, because it’ll be dangerous. For example, if k=3, we cannot build these 3 tramways simultaneously: p1-p14, p4-p9, p6-p8, because p7 would be dangerous.
You want to make this system as useful as possible, so you would like to maximize the total length of all tramways. For example, if m=3, k=3, the best design for the figure above is p1-p14, p2-p4 and p4-p9, the total length is 20. If m=3, k=2, you have to replace p1-p14 with p11-p13, the total length becomes 9.

输入

There will be at most 200 test cases. Each case begins with three integers n, m and k(1<=n,m<=200, 2<=k<=10), the number of points, the number of trams in your design and the dangerous parameter introduced earlier. The next line contains n pairs of positive integers xi and yi.(1<=xi,yi<=105). 

输出

For each test case, print the case number and the maximal sum. If it is impossible to have exactly m tramways, print -1. 

样例输入

14 3 3 

1 8
 
2 6
 
3 4
 
4 6
 
5 3
 
6 4
 
7 1
 
8 4
 
9 6
 
10 4
 
11 6
 
12 5
 
13 6
 
14 8
 
14 3 2
 
1 8 

2 6
 
3 4
 
4 6
 
5 3
 
6 4

7 1
 
8 4
 
9 6
 
10 4
 
11 6
 
12 5
 
13 6
 
14 8 

样例输出

Case 1: 20 

Case 2: 9 

提示

123

B: 大还是小?

时间限制: 1 Sec  内存限制: 128 MB
提交: 49  解决: 23
[提交][状态][讨论版]

题目描述

输入两个实数,判断第一个数大,第二个数大还是一样大。每个数的格式为:

[整数部分].[小数部分] 
简单起见,整数部分和小数部分都保证非空,且整数部分不会有前导 0。不过,小数部分的最 后可以有 0,因此 0.0和 0.000是一样大的。 


输入

输入包含不超过 20组数据。每组数据包含一行,有两个实数(格式如前所述)。每个实数都 包含不超过 100个字符。 

输出

对于每组数据,如果第一个数大,输出"Bigger"。如果第一个数小,输出"Smaller"。如果两个 数相同,输出"Same"。 

样例输入

1.0 2.0

0.00001 0.00000

0.0 0.000

样例输出

Case 1: Small
er
Case 2: Bigger

Case 3: Same

提示

123

比较一下  与HDU2059 类似;

#include<stdio.h>
#include<math.h>
#include<string.h>
#include <iostream>
 
using namespace std;
char a[100000],b[100000];
void change(char *a)
{
    int len;
    len=strlen(a);
    char *p;
    p=a+len-1;
    if(strchr(a,'.'))// a[]ÖÐÓÐ. Ôò·µ»ØλÖÃµÄ µØÖ· Èô ²»´æÔÚ ·µ»ØNULL 
    {
        while(*p=='0')   // .ºóÃæµÄ ÎÞЧ0È¥µô  
        {
            *p=NULL;
            p--;
        }
    }
    if(*p=='.')
    *p=NULL;
}
int main()
{
    char *p1,*p2;
    int cont=0;
    while(~scanf("%s %s",a,b))
    {
        p1=a;p2=b;     
        while(*p1=='0')//Ç°ÃæµÄÎÞЧµÄ0 È¥µô   
            p1++;
        while(*p2=='0')
            p2++;
        change(a);change(b);
        printf("Case %d: ",++cont);
        if(strcmp(a,b)>0)
            printf("Bigger\n");
        else if(strcmp(a,b)<0)
            printf("Smaller\n");
        else
            printf("Same\n");
    }   
    return 0;
}


C: 多边形的公共部分

时间限制: 5 Sec  内存限制: 128 MB
提交: 18  解决: 8
[提交][状态][讨论版]

题目描述

给定两个简单多边形,你的任务是判断二者是否有面积非空的公共部分。如下图,(a)中的两个 矩形只有一条公共线段,没有公共面积。 

在本题中,简单多边形是指不自交(也不会接触自身)、不含重复顶点并且相邻边不共线的多 边形。 
注意:本题并不复杂,但有很多看上去正确的算法实际上暗藏缺陷,请仔细考虑各种情况。 


输入

输入包含不超过 100 组数据。每组数据包含两行,每个多边形占一行。多边形的格式是:第一 个整数 n 表示顶点的个数 (3<=n<=100),接下来是 n 对整数(x,y) (-1000<=x,y<=1000),即多边 形的各个顶点,按照逆时针顺序排列。 

输出

对于每组数据,如果有非空的公共部分,输出"Yes",否则输出"No"。 

样例输入

4 0 0 2 0 2 2 0 2

4 2 0 4 0 4 2 2 2

4 0 0 2 0 2 2 0 2

4 1 0 3 0 3 2 1 2 

样例输出

Case 1: No

Case 2: Yes

提示

123

D: 错误的算法

时间限制: 5 Sec  内存限制: 128 MB
提交: 47  解决: 19
[提交][状态][讨论版]

题目描述

有道题目是这样的: 
输入一个 n行 m列网格,找一个格子,使得它所在的行和列中所有格子的数之和最大。如果答 案不唯一,输出任意解即可。比如,在下面的例子中,最优解是(1,3),即第一行和的三列的交 点(行从上到下编号为 1~n,列从左到右编号为 1~m),所有 7个数之和为 35。 

 
快要比赛的时候,有一个裁判想到了这样一个算法:
首先找一行 r(1<=r<=n) 使得该行所有数之和最大,然后找一列 c(1<=c<=m) 使得该列 所有数之和最大,最后直接输出(r,c)。如果有多个满足条件的 r,输出最小的 r。对 于 c同样处理。 

显然,这个算法是错的,但它竟然通过了大部分测试数据!你能找出那些让这个错误算法得到 正确结果的“弱”数据,以便裁判们改进这些数据吗? 


输入

输入包含不超过 100组数据。每组数据第一行为两个整数 n, m (1<=n<=500, 1<=m<=500),即行 数和列数。以下 n行每行包含 m个 1~100的整数。输入的总大小不超过 2MB。 

输出

对于每组数据,如果错误算法能得到正确结果,输出"Weak",否则输出"Strong"。 

样例输入

4 4

5 5 5 5

1 1 5 1

1 1 5 1

1 1 5 1

5 4

2 5 1 1

1 1 9 1

1 1 1 1

1 1 1 1

1 1 1 1

样例输出

Case 1: Weak

Case 2: Strong

提示

123

用错误的 方法 找到 最大的 里面 最小的记录 位置; 注意  行列 多计算了一次

 

然后比较一下  看看 有没有 比他还大的 有 则 有弱数据;


#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
    int m,n,a[555][555],row[555],col[555];
    int count=1;
    while(scanf("%d%d",&n,&m)!=EOF){
        int max2=-1;
        int x1=1000,y1=1000;
        memset(row,0,sizeof(row));
        memset(col,0,sizeof(col));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&a[i][j]);
                row[i]+=a[i][j];
                col[j]+=a[i][j];
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                if(row[i]+col[j]-a[i][j]>max2){
                    max2=row[i]+col[j]-a[i][j];
                }
            }
        int maxx=-1;
        for(int i=1;i<=n;i++){
            if(row[i]>maxx){
                x1=i;
                maxx=row[i];
            }
        }
        maxx=-1;
        for(int i=1;i<=m;i++){
            if(col[i]>maxx){
                maxx=col[i];
                y1=i;
            }
        }
        maxx=row[x1]+col[y1]-a[x1][y1];
        int flag=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                if(row[i]+col[j]-a[i][j]>maxx){
                    flag=1;
                }
            }
        if(!flag)
            printf("Case %d: Weak\n",count++);
        else
            printf("Case %d: Strong\n",count++);
    }
    return 0;
}


F: 阶乘除法

时间限制: 5 Sec  内存限制: 128 MB
提交: 70  解决: 16
[提交][状态][讨论版]

题目描述

输入两个正整数 n, m,输出 n!/m!,其中阶乘定义为 n!= 1*2*3*...*n (n>=1)。 
比如,若 n=6, m=3,则 n!/m!=6!/3!=720/6=120。 
是不是很简单?现在让我们把问题反过来:输入 k=n!/m!,找到这样的整数二元组(n,m) (n>m>=1)。 
如果答案不唯一,n应该尽量小。比如,若 k=120,输出应该是 n=5, m=1,而不是 n=6, m=3,因为 5!/1!=6!/3!=120,而 5<6。

输入

输入包含不超过 100组数据。每组数据包含一个整数 k (1<=k<=109)。

输出

对于每组数据,输出两个正整数 n和 m。无解输出"Impossible",多解时应让 n尽量小。 

样例输入

120

1

210

样例输出

Case 1: 5 1

Case 2: Impossible

Case 3: 7 4

提示



从 k = n! / m!    已知 k   则 一定有  从 n-m+1  * n-m+2  * ...  n-1* n   =k;

所以   n一定是k 的因子; 

枚举n 和m 找因子相乘,

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <stdlib.h>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <vector>
#define mem(a,b) memset(a,b,sizeof(a))
#define findx(x) lower_bound(b+1,b+1+bn,x)-b
#define FIN      freopen("input.txt","r",stdin)
#define FOUT     freopen("output.txt","w",stdout)
#define S1(n)    scanf("%d",&n)
#define SL1(n)   scanf("%I64d",&n)
#define S2(n,m)  scanf("%d%d",&n,&m)
#define SL2(n,m)  scanf("%I64d%I64d",&n,&m)
#define Pr(n)     printf("%d\n",n)
 
using namespace std;
typedef long long ll;
const double PI=acos(-1);
const int INF=0x3f3f3f3f;
const double esp=1e-6;
const int maxn=1e6+5;
const int MOD=1e9+7;
const int mod=1e9+7;
int dir[5][2]={0,1,0,-1,1,0,-1,0};
 
int main ()
{
    ll k;
    int cont=0;
    while(~scanf("%lld",&k))
    {
        int flag=0;
        ll m,n;
        if(k==1)
            printf("Case %d: Impossible\n",++cont);
        else
        {
            for(ll i=2;i*(i-1)<=k&&!flag;i++)
            {
                if(k%i==0)
                {
                    ll ans=1;
                    for(ll j=i;j>=1&&!flag;j--)
                    {       
                        ans*=j;     
                        if(ans==k)
                        {
                            m=i;n=j-1;
                            flag=1;
                            break;  
                        }
                    }
                }
            }
            if(!flag)
                printf("Case %d: %lld %lld\n",++cont,k,k-1);            
            else
                printf("Case %d: %lld %lld\n",++cont,m,n);  
        }   
    }
    return 0;
}


123

H: 聊天止于呵呵

时间限制: 5 Sec  内存限制: 128 MB
提交: 33  解决: 13
[提交][状态][讨论版]

题目描述

(现代版)俗话说:流言止于智者,聊天止于呵呵。输入一段聊天记录,你的任务是数一数有 多少段对话“止于呵呵”,即对话的最后一句话包含单词 hehe或者它的变形。 
具体来说,我们首先提取出对话的最后一句话,把所有非字母的字符替换成空格,把所有字符 替换成小写,然后导出一个单词列表(由空格隔开),只要列表中的任何一个单词是 hehe,这 段对话就算作“止于呵呵”。比如,"Hi! Are you OK?" 会变成四个单词:hi, are, you, ok。注 意,单词列表可以是空的(比如,这句话是:"?!?!!") 
有些人喜欢使用 hehe的变形,这些变形也应被视为“呵呵”。为了简单起见,本题只考虑由 n(n>1)个 he连接而成的单词,比如 hehehe或者 hehehehe。注意,以 hehe为连续子串的其他单 词不应视为“呵呵”,比如 hehee,或者 ehehe。 
每两个不同人之间的所有对话算作“一段对话”。 

输入

输入仅包含一组数据,每行是一句对话,格式为:

人名 1->人名 2: 一句话.

每行最多包含 1000个字符,最多 100行。 

输出

输出“止于呵呵”的对话段落所占的百分比,四舍五入到最近的整数。输入数据保证答案不会 同时和两个整数最近。 

样例输入

A->B: Hello!
A->C: Hi!
B->A: Hehe
B->D: Hei!
D->B: How are you?
A->C: Hi???
A->C: Are you there?
B->D: Hehehei!
D->B: What does hehehei mean?
F->E: I want to hehehehehe yah.

样例输出

50%

提示

样例解释
A 和 B 之间的最后一句话是"Hehe".
A 和 C 之间的最后一句话是"Are you there?".
B 和 D 之间的最后一句话是"What does hehehei mean?".
E 和 F 之间的最后一句话是"I want to hehehehehe yah". 最后第一段和最后一段话是“止于呵呵”的(注意最后一段对话是以呵呵的变种结束),因此 比例是 50%。



123

J: 又一道简单题

时间限制: 5 Sec  内存限制: 128 MB
提交: 47  解决: 21
[提交][状态][讨论版]

题目描述

输入一个四个数字组成的整数 n,你的任务是数一数有多少种方法,恰好修改一个数字,把它 变成一个完全平方数(不能把首位修改成 0)。比如 n=7844,有两种方法:3844=622 和 7744=882。 

输入

输入第一行为整数 T (1<=T<=1000),即测试数据的组数,以后每行包含一个整数 n (1000<=n<=9999)。 

输出

对于每组数据,输出恰好修改一个数字,把 n变成完全平方数的方案数

样例输入

2

7844

9121

样例输出

Case 1: 2

Case 2: 0

提示

123

四个枚举:


#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
    int a[10005]={0};
    for(int i=1;i<=100;i++){
        a[i*i]=1;
    }
    int T;
    char s[10];
    scanf("%d",&T);
    for(int count=1;count<=T;count++){
        int ans=0;
        cin>>s;
        int p=(s[1]-'0')*100+(s[2]-'0')*10+(s[0]-'0')*1000+(s[3]-'0');
        for(int i=1;i<10;i++){
            int t=(s[1]-'0')*100+(s[2]-'0')*10+(s[3]-'0')+i*1000;
            if(a[t]==1&&t!=p){
                ans++;
            }
        }
        for(int i=0;i<10;i++){
            int t=(s[0]-'0')*1000+(s[2]-'0')*10+(s[3]-'0')+i*100;
            if(a[t]==1&&t!=p){
                ans++;
            }
        }
        for(int i=0;i<10;i++){
            int t=(s[1]-'0')*100+(s[0]-'0')*1000+(s[3]-'0')+i*10;
            if(a[t]==1&&t!=p){
                ans++;
            }
        }
        for(int i=0;i<10;i++){
            int t=(s[1]-'0')*100+(s[2]-'0')*10+(s[0]-'0')*1000+i;
            if(a[t]==1&&t!=p){
                ans++;
            }
        }
         
        printf("Case %d: %d\n",count,ans);
    }
    return 0;
}


posted @ 2017-09-01 17:40  Sizaif  阅读(447)  评论(0编辑  收藏  举报