码迷,mamicode.com
首页 > 其他好文 > 详细

物联网学生科协第三届H-star现场编程比赛

时间:2016-04-16 18:59:40      阅读:179      评论:0      收藏:0      [点我收藏+]

标签:

问题 A: 剪纸片
时间限制: 1 Sec 内存限制: 128 MB
题目描述
这是一道简单的题目,假如你身边有一张纸,一把剪刀,在H-star的比赛现场,你会这么做:
1. 将这张纸剪成两片(平行于短边剪开);
2. 将其中一片剪成一个圆,作为圆柱的底面;
3. 纸的另一片的一边沿着圆的周长将圆围起来,直到围成一圈,形成一个无盖的圆柱体。需要注意的是,纸片可能会有重叠部分。
聪明的你机智的你喜欢思考的你这时候就开始想,一张纸片按上述方式所组成的圆柱的最大体积是多少呢?请你用编程解决这个问题。

输入
输入第一行包含一个数字t代表接下来有t组数据;
接下来的t行,输入两个数字w, h(1 ≤ w ≤ h ≤ 100),分别代表纸片的宽和高。

输出
对每一组数据输出纸片所能构成的最大圆柱体的体积v(保留小数点的后三位小数)。

样例输入
3
10 10
10 50
10 30
样例输出
54.247
785.398
412.095
比较坑的是,PI必须用acos(-1)表示
这一题还是蛮简单的,可以算是纯数学问题,在这里就不赘述了,直接上代码

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
double PI = acos(-1);
double Min(double a, double b)
{
    return a < b ? a : b;
}
double Max(double a, double b)
{
    return a > b ? a : b;
}
int main()
{
    //freopen("6.in", "r", stdin);
    //freopen("6.out", "w", stdout);
    double w, h, r, ans1, ans2, ans;
    int t;
    cin >> t;

    while (t--)
    {
        scanf("%lf%lf", &w, &h);
        r = Min(w / 2.0, h /(2.0 * PI + 2.0));//以w为圆柱的高
        ans1 = PI * r * r * w;
        r = Min(w / (2.0 * PI), h / 3.0);
        ans2 = PI * r * r * (h - 2.0 * r);//以h-2r为圆柱的高
        ans = Max(ans1, ans2);
        printf("%.3lf\n", ans);
    }
    return 0;
}

问题 B: 废品收集记
时间限制: 1 Sec 内存限制: 128 MB
题目描述
敲代码不是唯一的出路,但是假如H-star题目太难了,让你放弃了以后当程序员的念头,放弃身边的那个Ta,那么你就有可能去捡破烂,假如你去捡破烂,就会碰到下述问题:
在河海有n个垃圾桶,每个垃圾桶里面都有价值为m,体积为b的废品。但是你的背包体积只有V,为了赚更多钱,为了身边的Ta更幸福,你每一次捡破烂,都希望自己体积为V的背包里装的废品价值尽量多。
所以你又想起你曾经敲过的代码,你决定写一个程序解决这个问题。

输入
输入一个数字t,表示有t组数据:
每一组数据有三行:
第一行:输入两个数字n,V(n <= 1000, V <= 1000);
n表示垃圾桶的数量,V表示背包的容量
第二行:输入包括n个数字,代表每个垃圾桶中废品的价值m
第三行:输入包括n个数字,代表每个垃圾桶中废品需要占用的背包的容量b

输出
输出你每次出去捡破烂背包所能装下破烂的最大价值(保证每次输出数据都在整形范围内)。

样例输入
1
5 10
1 2 3 4 5
5 4 3 2 1
样例输出
14

这是一道01背包的题目,想要了解01背包的,这边有一个博客的地址:http://www.cnblogs.com/xy-kidult/archive/2013/03/25/2970313.html
将问题一般化;

#include<stdio.h>
#include<string.h>
#define M 1009
typedef struct pack
{
    int cost;
    int val;
}PACK;
int main()
{
    int cas,n,v,i,j;
    int f[M];
    PACK a[M];
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&n,&v);
        memset(f,0,sizeof(f));
        for(i=1;i<=n;i++)
            scanf("%d",&a[i].val);
        for(i=1;i<=n;i++)
            scanf("%d",&a[i].cost);
        for(i=1;i<=n;i++)
            for(j=v;j>=a[i].cost;j--)
                if(f[j]<f[j-a[i].cost]+a[i].val)
                    f[j]=f[j-a[i].cost]+a[i].val; //01背包状态方程
        printf("%d\n",f[v]);
    }
    return 0;
}

问题 C: Northcott游戏
时间限制: 1 Sec 内存限制: 128 MB
题目描述
alpha和GrayGraySmall正在玩一种Northcott游戏,可是alpha老是输,因此他怀疑这个游戏是不是有某种必胜策略,郁闷的alpha现在向你求救了,你能帮帮他么?
游戏规则是这样的:
如图所示,游戏在一个n行m列(1 ≤ n ≤ 1000且2 ≤ m ≤ 100)的棋盘上进行,每行有一个黑子(黑方)和一个白子(白方)。执黑的一方先行,每次玩家可以移动己方的任何一枚棋子到同一行的任何一个空格上,当然 这过程中不许越过该行的敌方棋子。双方轮流移动,直到某一方无法行动为止,移动最后一步的玩家获胜。alpha总是先下(黑方)。图1是某个初始局面,图二是 alpha移动一个棋子后的局面(第一行的黑子左移两步)。

技术分享

输入
输入数据有多组。每组数据第一行为两个整数n和m,由空格分开。接下来有n行,每行两个数Ti,Ji (1 ≤ Ti, Ji ≤ m)分别表示alpha和GrayGraySmall在该行棋子所处的列数。
注意:各组测试数据之间有不定数量的空行。你必须处理到文件末。

输出
对于每组测试数据输出一行你的结果。如果当前局面下alpha有必胜策略则输出“I WIN!”,否则输出“BAD LUCK!”。

样例输入
3 6
4 5
1 2
1 2
样例输出
BAD LUCK!

夏黑出的博弈论。。。我就不说什么了,他是说反正没人能做出来

#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;

int main(){
    int n, m;
    while(scanf("%d%d", &n, &m)!=EOF){
        m = 0;                          //这里注意m并没有什么用处我就懒得多定义一个变量了直接拿来用了
        int a, b;

        while(n--){
            scanf("%d%d", &a, &b);
            m ^= abs(a-b) - 1;
        }

        if(m){
            printf("I WIN!\n");
        }
        else{
            printf("BAD LUCK!\n");
        }
    }
    return 0;
}

问题 D: 我在NE304敲代码的时候吃女神送给我的糖果
时间限制: 1 Sec 内存限制: 128 MB
题目描述
一个立志做程序员的人,做什么都会想到敲代码。小明的女神曾经送给他一堆糖果,但是他一直舍不得吃,最后等到了H-Star比赛,小明就把女神送给他的苹果带到了比赛现场,当作女神对他的祝福。但是问题往往就在这时候浮现在他的脑海:
小明有一个癖好,吃糖果的时候,不喜欢连着吃同一种糖果,喜欢先吃一种,下一次吃另一种(小明一次只吃一颗糖果);可是小明不知道是否存在一种吃糖果的顺序使得他能把所有糖果都吃完。
小明认为这是女神对他的一个考验,也是祝福,所以马上在NE304敲起了代码…

输入
第一行有一个整数T,接下来T组数据,每组数据占2行,第一行是一个整数N(0

#include<stdio.h>
long long sum;
int main()
{
   int n,i,num,maxn,cas;
   scanf("%d",&cas);
   while(cas--)
   {
       scanf("%d",&n);
      sum=maxn=0;
      for(i=0;i<n;i++)
      {
       scanf("%d",&num);
       if(num>maxn) maxn=num;
         sum+=num;
      }
      if(sum-maxn+1>=maxn) puts("Yes");
      else puts("No");
   }
   return 0;
}

问题 E: Lecture

时间限制: 1 Sec 内存限制: 128 MB
题目描述

coco有一个说话特别特别快的新图论老师,因为说话太快所以coco虽然勉强能跟得上老师的课但是却没办法记好笔记,好在coco很聪明,她想到了一个方法让自己跟得上课并记笔记。
coco知道两种语言,而老师上课的时候总是用第一种语言,语言中的单词都是由英文小写字母组成,每一门语言又由几个单词组成。对每一门语言来说,所有的单词都是相互独立的,只是拼写不同。而且,对于这些语言来说每个单词都是一一对应的,对于一门语言的一个单词来说,它都会在另一门语言中有确切的单词和确切的意思.。
coco可以卸下老师讲的每一个单词,不管是第一种语言还是第二种语言。当然,在上课期间coco写下的每一个单词都是这两种语言中最短的那个。如果单词长度一样,coco会倾向于写第一种语言。
现在给你一段老师讲课的文本,找出这节课coco会在笔记本上记录的内容。
输入

第一行包含两个整数,n和 m( 1<= n,m <= 3000), 老师堂内容的单词数和这些语言中的单词数。
接下来的 m 行包含了这些单词.第 i行包含两个串 ai, bi。ai是第一门语言的单词, bi是第二门语言的单词,这两个单词拥有相同的意思.输入保证没有相同的单词出现在两种语言中,而且每个单词在一中语言中只出现一次.
接下来的一行有 n 个空格隔开的串 c1,c2,…,cn —讲课的内容.保证每一个 Ci串都会在集合{a1,a2,…am}中.
所有的串在输入中都不空,每一个单词都由不超过10个英文小写字母组成.
输出

输出有 n个单词::你将会记录在笔记本中的讲课内容。单词顺序不变。
样例输入

4 3
codeforces codesecrof
contest round
letter message
codeforces contest letter contest
样例输出

codeforces round letter round

这是今天第二简单的题目,就是简单的字符串的应用,大家大一上的时候会觉得字符串特别难,但是现在可能就不觉得了。
我的方法是简单的直接搜索一遍就好了

#include <stdio.h>
#include <string.h>
#define maxn 3005

char a[maxn][15], b[maxn][15];
int findStr( char *c, int m ){
    for( int i = 0; i < m; i++ )
        if( strcmp( c, a[i] ) == 0 )
            return i;
    return -1;
}

int main(){
    int n, m;
    char c[15];
    scanf( "%d %d", &n, &m );
    for( int i = 0; i < m; i++ )
        scanf( "%s %s", a[i], b[i] );
    for( int i = 0, ok = 0; i < n; i++ ){
        scanf( "%s", c );
        int t = findStr( c, m );
        ok ? printf( " " ) : ok = 1;
        if( strlen( a[t] ) > strlen( b[t] ) )
            printf( "%s", b[t] );
        else
            printf( "%s", a[t] );
    }
    return 0;

}

问题 F: 回文数
时间限制: 1 Sec 内存限制: 128 MB
题目描述
回文数是顺着读和反着读都一样的数字,给你一个数字,请你判断它是不是回文数。

输入
输入一个整数t(t在int范围内)

输出
如果这个数是回文数,则输出Yes,如果不是回文数,则输出No

样例输入
121
样例输出
Yes

签到题。。

#include <stdio.h>

int main()
{
    int num, t;
    int sum = 0;
    scanf("%d", &num);
    t = num;
    while(num)          //将一个数转置,和原来的数字相同,就是回文数
    {
        sum = sum*10 + num%10;
        num /= 10;
    }

    if(t == sum)
        printf("Yes\n");
    else
        printf("No\n");
    return 0;
}

问题 G: 小明和他的嵌套娃娃
时间限制: 1 Sec 内存限制: 128 MB
题目描述
小明有一个收藏嵌套娃娃的爱好,嵌套娃娃是这样的一种娃娃,一个娃娃a1的宽为w1,高为h1,另一个嵌套娃娃a2的宽为w2,高为h2,如果h1 > h2 并且 w1 > w2,则a2 可以嵌进a1;

小明有m个娃娃,他想在他女神生日的时候将他的所有娃娃都送给他女神,为了制造出一种“惊喜”的效果,他想要将小的娃娃尽量多的嵌套在大的娃娃里面,他认为这样的话,他的女神会“exciting”,他给你这些娃娃的宽和高,你能帮帮他,将这些娃娃尽量“少”的分组吗?

输入
第一行输入包括一个正整数t,表示接下来有t组数据(1 ≤ t ≤ 20),接下来的t组数据,每一组数据都包含一个正整数m,表示有m个娃娃(1 ≤ m ≤ 20000), 下一行包含 2m 个整数w1, h1,w2, h2, … ,wm, hm,

wi 和 hi 分别表示第i个娃娃的宽和高,对于所有的w,h都有( 1 ≤ wi, hi ≤ 10000).

输出
输出一个数字,表示最少可以分为几组。

样例输入
4
3
20 30 40 50 30 40
4
20 30 10 10 30 20 40 50
3
10 30 20 20 30 10
4
10 10 20 30 40 50 39 51
样例输出
1
2
3
2
这道题有一个超时的坑,可是没有人做出来

可以直接剪枝。。。考的是离散数学的偏序问题
原题地址:POJ 3636,想看详解的话,直接百度也可以
或者使用二分法。。。第一步是直接排序。。。。
好了。。。上代码

#include<stdio.h>
#include<algorithm>
using namespace std;
#define Max 20001
struct D{
    int w,h;
}d[Max];
D dd[Max];

bool cmp(D x,D y)//w升序,h降序可以保证w相等时,一定不会出现覆盖的情形。
{
    if(x.w==y.w) return x.h>y.h; 
    return x.w<y.w; 
}
int main()
{
    int n,i,j,m;
    scanf("%d",&n);
    while(n--)
    {
        int result=0;
        scanf("%d",&m);
        for(i=0;i<m;i++)
            scanf("%d%d",&d[i].w,&d[i].h);
        sort(d,d+m,cmp);
        for(i=0;i<m;i++)
        {
            int flag=0;
            for(j=0;j<result;j++)
                if(d[i].w>dd[j].w&&d[i].h>dd[j].h)
                {
                    dd[j]=d[i];
                    flag=1;
                    break;
                }
                if(!flag) dd[result++]=d[i];
        }
        printf("%d\n",result);
       }
    return 0;
}

问题 H: 优秀的三名研究生
时间限制: 1 Sec 内存限制: 128 MB
题目描述
ACM实验室的alpha教授手下有三个研究生,每学期初alpha教授会给他们安排若干任务,每个任务都有相应的难度值,教授要求每学期必须把所有任务全部完成,而且难度值小的任务要先完成。
教授的三个研究生都是很优秀的学生,完成这些任务对他们来说并没有什么困难,但是因为彼此都很优秀,所以都不愿意和其他人一样,于是他们都想自己完成任务的顺序和其他人不一样。

输入
输入数据第一行是一个正整数 n (1?≤?n?≤?2000) — 任务的数量。

第二行包括n个整数h1, h2,…,hn(1?≤?hi?≤?2000), hi代表第i个任务的难度值。

输出
如果任务可以存在三种不同的完成顺序,则第一行输出“YES”, 接下来三行输出三种完成任务的顺序,如果有超过三种完成任务的顺序,则先对较低难度值任务字典序排列,再对较高难度值任务字典序排列,依次输出前三种。

如果任务不存在三种不同的完成顺序,则只要输出“NO“。

样例输入
4
1 3 3 1
样例输出
YES
1 4 2 3
4 1 2 3
4 1 3 2
夏黑的题目,我就不说什么了,直接上代码:

#include<algorithm>
#include<iostream>
using namespace std;
int main()
{
    int n;
    cin>>n;
    pair<int,int> a[n];
    int now=0;
    for(int i=0;i<n;i++)cin>>a[i].first,a[i].second=i;
    sort(a,a+n);
    for(int i=0;i<n-1;i++)if(a[i].first==a[i+1].first)now++;
    if(now<2)
    {
        cout<<"NO\n";
        return 0;
    }
    int w=0;
    cout<<"YES\n";
    for(int i=0;i<n;i++)cout<<a[i].second+1<<" ";
    cout<<endl;
    for(int i=0;i<n,w!=2;i++)
    {
        if(a[i].first==a[i+1].first)
        {
            swap(a[i],a[i+1]);
            for(int j=0;j<n;j++)cout<<a[j].second+1<<" ";
            cout<<endl;
            w++;
        }
    }

    return 0;
}

问题 I: alpha特工学院
时间限制: 1 Sec 内存限制: 128 MB
题目描述
alpha特工学院现在有n名学员,校长alpha用严格的规章制度给他们以史上最残酷的特工训练。
特工学院新学期即将到来,新学期将会持续d天,每天有k辆车接送学员上学。因为是特工训练,所以校长alpha是不允许学员们彼此之间成为朋友的,所以alpha规定,在这k天时间里面,任意两个学员最多只能有一天的时间是乘坐同一辆车的。
那么问题来了,教务老师在排学员的每天乘车方案时遇到了问题,聪明的小伙伴你可以帮助教务老师解决这个问题,让她不至于被校长责备么?

输入
输入数据第一行是三个正整数 n,?k,?d (1?≤?n,?d?≤?1000; 1?≤?k?≤?1000000000).

输出
如果找不到完美的解决方案则输出-1.
如果有完美解决方案则输出d行,每一行n个数字,第i行第j个数字表示第j学生
必须在第i天乘坐这辆车。
如果有多组输出,请参考样例的输出顺序。
校车的命名采用正整数从1-k。

样例输入
3 2 2
样例输出
1 2 1
1 1 2
还是夏黑的题,自己看看吧= =
还是没人做

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
    int n, k, d, i, j, v[1000];
    long long x=1;
    cin>>n>>k>>d;
    for (i=0; i<d && x<n; i++) x*=k;
    if (x<n) cout<<-1<<endl;
    else {
        for (i=0; i<n; i++) v[i]=i;
        for (i=0; i<d; i++) {
            for (j=0; j<n; j++) {
                cout<<v[j]%k+1<<" ";
                v[j]/=k;
            }
            cout<<endl;
        }
    }
    return 0;
}

问题 J: 遍历 遍历 遍历
时间限制: 1 Sec 内存限制: 128 MB
题目描述
给你一个树,请你从上到下,从左到右,遍历树的每一个节点。

输入
第一行输入一个数N (N<=10),代表总结点数,结点被从0~N-1编号;
接下来的n行,每行输入两个数,分别代表结点的左右孩子结点;
如果一个结点没有左右孩子,则用“-”表示,左右孩子之间用空格分开。

输出
根据你遍历树的顺序(从上到下,从左到右),依次输出叶子结点;结点之间用空格隔开,结尾没有空格。

样例输入
8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6
样例输出
4 1 5
数据结构。。。二叉树的广度优先搜索。。。。

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
struct Node {
    int lchild;
    int rchild;
    Node() {
        lchild = -1;
        rchild = -1;
    }
};
Node node[20];
int n, flag = 0;
bool findroot[20];
char l, r;
queue<int> q;
void bfs(int i) {
    q.push(i);
    while(!q.empty()) {
        int cur = q.front();
        q.pop();
        if(node[cur].lchild == -1 && node[cur].rchild == -1) {
            if(flag == 0) {
                printf("%d", cur);
                flag = 1;
            } else {
                printf(" %d", cur);
            }
        }
        if(node[cur].lchild != -1) {
            q.push(node[cur].lchild);
        }
        if(node[cur].rchild != -1) {
            q.push(node[cur].rchild);
        }
    }
    printf("\n");
}
int main() {
    memset(findroot, false, sizeof(findroot));
    scanf("%d", &n);
    getchar();
    for (int i = 0; i < n; i ++) {
        scanf("%c %c", &l, &r);
        getchar();
        if(isdigit(l)) {
            node[i].lchild = l - ‘0‘;
            findroot[node[i].lchild] = 1;
        }
        if(isdigit(r)) {
            node[i].rchild = r - ‘0‘;
            findroot[node[i].rchild] = 1;
        }
    }
    for (int i = 0; i < n; i ++) {
        if(findroot[i] == 0) {
            bfs(i);
            break;
        }
    }
    return 0;
}

祝大家决赛取得好成绩,没了。

物联网学生科协第三届H-star现场编程比赛

标签:

原文地址:http://blog.csdn.net/chedan666/article/details/51168230

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!