物聯網學生科協第三屆H-star現場程式設計比賽

weixin_33912246發表於2017-08-10

問題 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;
}

祝大家決賽取得好成績。沒了。

相關文章