2020年寒假訓練賽IV

問題 A: 時鐘

題目描述

有一個標準的12小時時鐘,它有一個時針,一個分針。現問你,在給定的兩個時刻之間分針與時針相遇幾次?

輸入

輸入包含多組測試數據。每組輸入包含4個整數,前兩個數字分別表示起始時刻的小時和分,後兩個數字分別表示結束時刻的小時和分。
小時數在[1,12]內,分鐘數在[0,59]內。
注意:
1)輸入中的起始和結束時刻均不會出現時針和分針恰好相遇的情況,例如12點0分。
2)輸入中不會出現起始時刻和結束時刻相同的情況。
3)在時針從起始時刻到結束時刻運轉的過程中,時針轉過的角度一定小於360度。
4)在時針從起始時刻到結束時刻運轉的過程中,時針有可能越過錶盤上12點鐘的刻度。如果越過了,說明起始時刻和結束時刻中一個是A.M.,一個是P.M.。如果沒越過,說明起始時刻和結束時刻都是A.M.或都是P.M.。

輸出

輸出的第一行爲“Initial time  Final time  Passes”,具體的輸出格式請參照輸出樣例。可用鼠標選中來看出空格數等細節。

樣例輸入

12 50  1  2
 3  8  3 20
 2 45 11  0
11  0  3 20
 1  2 12 50
 3 20  3  8

樣例輸出

Initial time  Final time  Passes
       12:50       01:02       0
       03:08       03:20       1
       02:45       11:00       8
       11:00       03:20       4
       01:02       12:50      11
       03:20       03:08      10

題解:

模擬

從時鐘開始時刻到 終止時刻路程轉化成分鐘,之間相差多少圈基本就相遇幾次。

每12小時相遇11次。 所以時間差*11/720即可。 

最後注意一下輸出格式,可用鼠標選中來看出空格數等細節。

代碼:

#include<bits/stdc++.h> 
using namespace std;
int main()
{
    cout<<"Initial time  Final time  Passes"<<endl;
    int h1, m1, h2, m2;
    while(cin>>h1>>m1>>h2>>m2)
    {
        int s1 = h1, s2 = m1, s3 = h2, s4 = m2;//存儲起始時間
        h1 %= 12;
        h2 %= 12;
        if(h2<h1) h2 += 12;
        else if(h2 == h1 && m2<=m1)h2 += 12;
        int t1 = (h1*60+m1)*11;
        int t2 = (h2*60+m2)*11;//轉化分鐘
        int ans = t2/720 - t1/720;//公式
        printf("       %02d:%02d       %02d:%02d", s1,s2,s3,s4);//注意格式
        printf("%8d\n", ans);
    }
    return 0;
}

問題 B: 舞伴的搭配(partner)

題目描述

學校將要舉行一年一度的文藝匯演,笑笑所在年級決定排練一個舞蹈,爲選擇表演者,老師定下了如下規則:爲了舞蹈的美觀,當且僅當一男一女的身高之差不超過給定的整數c時,這兩個人可以成爲舞伴進行演出。笑笑所在年級共有m名男生和n名女生,給定每個人身高(身高是120到220之間的整數),問最多能有多少對舞蹈者進行演出。

例如,有3名女生和3名男生,女生的身高分別是160釐米、170釐米、180釐米,男生的身高分別爲170釐米、175釐米、185釐米,c=7釐米。那麼最多有2對舞蹈者:可以是女2和男1一組,女3和男2一組,共2組(女1不能和任何男生成爲一組),所以這個情況下2將成爲最後的答案。

輸入

輸入分三行:

第一行三個整數m、n、c,分別表示男生人數、女生人數和身高最大差值。

第二行m個整數,分別表示m個男生的身高。

第三行n個整數,分別表示n個女生的身高。

輸出

僅一個整數,表示舞蹈者組數的最大數目。

樣例輸入

3 3 7
170 185 175
160 170 180

樣例輸出

2

提示

數據規模:

100%數據,滿足m,n≤1000

題解:

貪心

大致思路:男生和女生的身高先排個序,再一個個匹配

但是怎麼匹配呢?

先找男生第一個和女生第一個匹配,

如果身高差>c且男生更矮就下一個男生

如果身高差>c且女生更矮就下一個女生

如果身高差<=c——匹配成功

代碼:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
int man[MAXN],woman[MAXN];
int m,n,c;
int main()
{
    cin>>m>>n>>c;
    for(int i = 1;i <= m; ++i) cin>>man[i];
    for(int i = 1;i <= n; ++i) cin>>woman[i];
    sort(man + 1,man + 1 + m,cmp);//男生排序
    sort(woman + 1,woman + 1 + n,cmp);//女生排序
    int num1 = 1,num2 = 1,cnt = 0;         
    while(num1 <= m && num2 <= n)
    {   
        if(man[num1] - woman[num2] > c) num2++; //如果女生矮
        else if(woman[num2] - man[num1] > c) num1++;  //如果男生矮 
        else
        {
            num1++;
            num2++; 
            cnt++;
        }
    }
    printf("%d\n",cnt);
}

問題 C: 心急的C小加

題目描述

C小加有一些木棒,它們的長度和質量都已經知道,需要一個機器處理這些木棒,機器開啓的時候需要耗費一個單位的時間,如果第i+1個木棒的重量和長度都大於等於第i個處理的木棒,那麼將不會耗費時間,否則需要消耗一個單位的時間。因爲急着去約會,C小加想在最短的時間內把木棒處理完,你能告訴他應該怎樣做嗎?

輸入

第一行是一個整數T(1<T<1500),表示輸入數據一共有T組。
每組測試數據的第一行是一個整數N(1<=N<=5000),表示有N個木棒。接下來的一行分別輸入N個木棒的L,W(0 < L ,W <= 10000),用一個空格隔開,分別表示木棒的長度和質量。

輸出

處理這些木棒的最短時間。

樣例輸入

3 
5 
4 9 5 2 2 1 3 5 1 4 
3 
2 2 1 1 2 2 
3 
1 3 2 2 3 1 

樣例輸出

2
1
3

題解:

貪心算法+Dilworth定理

1.將木塊按照長度上升排序,如果,長度相等,那麼,按照重量的大小升序排序。

2.主要是貪心算法+Dilworth定理,因爲,兩個結點之間,當長度和重量都大於前面的結點,那麼,符合我們的要求,所以,可以將已經排序好的序列,分成多個序列,這些序列是按照重量的大小來排序,然後儘可能多的找出符合要求的結點,這裏主要用到了貪心算法。

3.我們只要統計有多少個序列,就是得到的結果。

代碼:

#include<bits/stdc++.h>
using namespace std; 
struct Node
{
    int l,w;
}data[5005]; 
int vis[5005]; 
int T,n;
int cmp(Node a,Node b)
{
    if(a.l < b.l)return 1;
    else if(a.l == b.l && a.w < b.w)return 1;
    return 0;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i = 1;i <= n; ++i)
            scanf("%d%d",&data[i].l,&data[i].w);
        memset(vis,0,sizeof(vis));
        sort(data + 1,data + 1 + n,cmp);
        int cnt = 0,zl; 
        for(int i = 1;i <= n; ++i)   
            if(!vis[i]) 
            {   
                cnt++;
                zl = data[i].w;
                for(int j = i + 1;j <= n; ++j)
                    if(zl <= data[j].w && !vis[j]) 
                    {
                        vis[j] = 1;
                        zl = data[j].w; 
                    }
            }
        printf("%d\n",cnt);
    }
    return 0;
}

問題 D: 摧毀巴士站

題目描述

Gabiluso是最偉大的間諜之一。現在,他試圖完成一個“不可能完成”的使命――減緩Colugu的軍隊到達機場的時間。Colugu有n個公共汽車站和m條道路。每條道路直接連接兩個巴士站,所有的道路都是單向的。爲了保持空氣潔淨,政府禁止所有軍用車輛,因此,軍隊必須乘搭巴士去機場。兩個巴士站之間,可能有超過一條道路。如果一個公共汽車站被破壞時,所有連接該站的道路將無法運作。Gabiluso需要做的是摧毀了一些公共汽車站,使軍隊無法在K分鐘內到達機場。一輛公交車通過一條道路,都是一分鐘。所有巴士站的編號從1到n。1號巴士站是在軍營,第n號站是機場。軍隊始終從第一站出發。第一站和第n站不能被破壞,這裏有大量的防禦力量。當然也沒有從第一站到第n站的道路。
請幫助Gabiluso來計算能完成使命所需摧毀的最低數目的巴士站。

輸入

第一行包含三個整數n,m,k (2<n<=50,0<m<=4000,0<k<1000)。

接下來m行,每行2個整數s和f,表示從站s到站f有一條路。

輸出

輸出最少需要摧毀的巴士站數目。

樣例輸入

 

樣例輸出

 

提示

【數據規模】
30%的數據N<=15。

題解:

遞歸摧毀某個點,然後spfa判斷。但是有些點,可能經過他的路徑,長度都是大於k的,那麼這些點就不必要進行遞歸。於是,我們每次找一次最短路,看看從1~n的最短路分別經過了哪幾個點。因爲這裏面的點都是在不符合條件的最短路里,所以我們遞歸那些經過的點刪或者不刪,直到最短路符合k的條件爲止,取一個刪的數目最少的爲答案即可。

代碼:

#include<bits/stdc++.h> 
using namespace std;
int n,m,k,ans=1e9;
int a[55][55],dis[55],f[55],g[55][55];
int vis[55],flag[55];
queue<int> Q;
void SPFA()//SPFA模板
{
    memset(dis,0x7f,sizeof(dis));
    dis[1] = 0;
    Q.push(1);
    while(!Q.empty())
    {
        int x = Q.front();
        Q.pop();
        vis[x] = 0;
        for(int i = 1;i <= n; ++i)
            if(!flag[i] && a[x][i] && a[x][i]+dis[x] < dis[i])
            {
                dis[i] = dis[x] + a[x][i];
                f[i] = x;
                if(!vis[i]) Q.push(i);
            }
    }
}
void check(int x,int y)//遞歸刪點
{
    if(x == 1) return;
    check(f[x],y);
    g[y][++g[y][0]] = x;
}
void dfs(int x)
{
    if(x >= ans) return;
    memset(f,0,sizeof(f));
    SPFA();//跑最短路
    if(dis[n] > k)
    {
        ans = min(ans,x);
        return;
    }
    g[x][0] = 0;
    check(n,x);
    for(int i = 1;i < g[x][0]; ++i)
    {
        flag[g[x][i]] = 1;//標記,意爲刪除此點
        dfs(x + 1);
        flag[g[x][i]] = 0;//還原現場,回溯
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i = 1;i <= m; ++i)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        a[x][y] = 1;
    }
    dfs(0);
    printf("%d\n",ans);
    return 0;
}

問題 H: 競技遊戲

題目描述

小灰灰和小東東在玩一種競技遊戲。在遊戲中,小灰灰給小東東由n個正整數組成的序列以及m條操作指令,需要小東東按照指令來對n個整數進行操作。其中每條指令都包括二個整數(a, b),意義如下:

如果a大於0,表示將序列中第b個數乘於2;

如果a小於0,表示將序列中第b個數加上2;

如果a等於0,則忽略此條指令。

遊戲結束後,小東東需要求出序列中的最大值。現在小東東求助於你,希望你能用計算機編程求出他需要的答案。題目保證計算結果在int的表示範圍內。

輸入

輸入數據第一行爲一整數T,表示有T組數據。每組輸入數據第一行有二個整數n, m, (1 <= n <= 100), (1 <= m <= 100), 第二行有n個整數(1 ~100),表示初始序列,編號從1...n。接着是m行表示m條指令,每行共有2個用空格隔開的整數a b,(-50<= a <= 50), (1 <= b <= n)。

 

輸出

對於每組數據,輸出一個整數佔一行,表示操作後的序列中的最大整數。

樣例輸入

2
2 2
1 2
1 1
-1 2
3 4
1 5 6
1 1
1 1
0 1
-1 1

樣例輸出

4
6

題解:

入門的模擬題

代碼:

#include<bits/stdc++.h>
const int MAXN = 105;
using namespace std;
int T,n,m,a,b;
int Array[MAXN];
int max_ans;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n; ++i)
            scanf("%d",&Array[i]);
        while(m--)
        {
            scanf("%d%d",&a,&b);
            if(a > 0)
                Array[b] *= 2;
            else if(a < 0)
                Array[b] += 2;
        }
        max_ans = Array[1];
        for(int i = 1;i <= n; ++i)
            max_ans = max(max_ans,Array[i]);
        printf("%d\n",max_ans);
    }
    return 0;
}

問題 I: 手機話費

題目描述

小明的手機每天消費1元,每消費K元就可以獲贈1元,一開始小明有M元,問最多可以用多少天?

輸入

輸入包括多個測試實例。每個測試實例包括2個整數M,K(2<=k<=M<=1000)。M=0,K=0代表輸入結束。

輸出

對於每個測試實例輸出一個整數,表示M元可以用的天數。

樣例輸入

2 2
4 3
0 0

樣例輸出

3
5

題解:

語言基礎題

代碼:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int m,k;
    while(cin>>m>>k&&m&&k)
    {
        int a=0;
        int count=0;
        while(m)
        {
            m--;
            count++;
            a++;
            if(a==k)
            {
                m++;
                a=0;
            }
        }
        cout<<count<<endl;
    }
    return 0; 
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章