1. 程式人生 > >2018第一次校隊集訓題解

2018第一次校隊集訓題解

問題 A: 豆豆強的蛋糕店

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 29  解決: 3
[提交] [狀態] [討論版] [
命題人:外部匯入

題目描述

豆豆強是一個人名,曾經是一名ACMer
通過打鬥地主、錄視訊、作解說、開淘寶店等,豆豆強終於成功走上了致富之路。
資金充足的豆豆強最近開了一家蛋糕店,作為一名特立獨行的人,豆豆強受不了普通顧客要多少就賣給顧客多少蛋糕的運營模式,於是他提出了一種隨機賣蛋糕模式,對於來買蛋糕的顧客,豆豆強會根據顧客購買蛋糕的多少提供不同長度的木棍,然後顧客隨機投擲到蛋糕表面上(保證木棍不會插在蛋糕上,但有可能沒有投擲到蛋糕上),那麼這根木棍繞蛋糕中心(也是座標原點)旋轉一週後覆蓋的蛋糕就是顧客獲得的蛋糕。


注:由於工藝問題,豆豆強的蛋糕店只生產表面是長方形的蛋糕。

輸入

輸入資料第一行是caseT(1<= T <= 1000)
接下來有Tcase,每組case第一行三個整數n,m,sum,分別表示蛋糕的長、寬和顧客要買的蛋糕面積;
第二行四個整數x1,y1,x2,y2,表示顧客投擲木棍的兩端點座標。
1<= m <= n <= 1000
-1000<= x1,y1,x2,y2 <=1000

輸出

如果顧客獲得的蛋糕面積大於等於顧客想要的輸出”YES”,否則輸出”NO”
每組資料輸出一行。

樣例輸入

複製

2

4 4 4

0 2 3 4

10 10 65

0 2 3 4

樣例輸出

複製

NO

YES

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define PI 3.1415926535898
 
using namespace std;
 
double PointToPoint(double x1,double y1,double x2,double y2) {
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
 
double PointToSegDist(double x,double y,double x1,double y1,double x2,double y2){
    double cross=(x2-x1)*(x-x1)+(y2-y1)*(y-y1);
    if(cross<=0) return sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1));
    double ab2=(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
    if(cross>=ab2) return sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2));
    double r=cross/ab2;
    double dx=x1+(x2-x1)*r;
    double dy=y1+(y2-y1)*r;
    return sqrt((x-dx)*(x-dx)+(y-dy)*(y-dy));
}
 
double AraeToArcuate(double m,double r){
    return acos(m/r)*r*r-sqrt(r*r-m*m)*m;
}
 
double CircularAreaRectangle(double n,double m,double r){
    if(n>m){double t=n;n=m;m=t;}
    double diagonal=sqrt(n*n+m*m);
    if(r<n)
        return PI*r*r;
    else if(n<=r && r<=m)
        return PI*r*r-2*(acos(n/r)*r*r-sqrt(r*r-n*n)*n);
    else if(m<r && r<=diagonal)
        return PI*r*r-2*(acos(n/r)*r*r-sqrt(r*r-n*n)*n)-2*(acos(m/r)*r*r-sqrt(r*r-m*m)*m);
    else
        return m*n*4;
}
 
int main(){
    int T;
    cin >> T;
    while(T--){
        double n,m,sum;
        double x1,x2,y1,y2;
        cin >> n >> m >> sum;
        cin >> x1 >> y1 >> x2 >> y2;
        double x=0,y=0;
        double near=PointToSegDist(x,y,x1,y1,x2,y2);
        double d1=PointToPoint(x,y,x1,y1);
        double d2=PointToPoint(x,y,x2,y2);
        double far=d1>d2?d1:d2;
        double area1=CircularAreaRectangle(n/2,m/2,near);
        double area2=CircularAreaRectangle(n/2,m/2,far);
        double area=area2-area1;
        cout << (area>=sum||sum==0?"YES\n":"NO\n");
 
    }
    return 0;
}

問題 B: 找方塊

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 19  解決: 9
[提交] [狀態] [討論版] [
命題人:外部匯入

題目描述

小明最近看到一件藝術品,是由許多黑白方塊組成的矩形圖,但是並不是黑白相間的。小明希望找到一個最大的黑白相間的矩形。

輸入

第一行輸入T(T<=10)
接下來輸入T組資料,每組資料第一行為N,表示這個藝術品的矩陣大小是N * NN <=100)。
接下來是一個N * N的矩陣,0代表黑色,1代表白色。

輸出

對於每組資料,輸出最大的黑白相間矩形的面積。
每組輸出佔一行。

樣例輸入

複製

1

2

0 1

1 0

樣例輸出

複製

4

2017hdu新生賽2017內蒙古ACM-ICPC省賽,一道模擬題,控制好行列掃就行了。

#include<iostream>
using namespace std;
int p[105][105];
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int area=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++)cin>>p[i][j];
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                int down=i;
                int right=j;
                for(int k=i+1;k<n;k++){
                    if(p[k][j]!=p[k-1][j])down++;
                    else break;
                }
                for(int k=j+1;k<n;k++){    
                    if(p[i][k]!=p[i][k-1])right++;
                    else break;
                }
                for(int k=i;k<=down;k++){
                    bool flag=true;
                    for(int l=j+1;l<=right;l++){
                        if(p[k][l]==p[k][l-1]){
                            int narea=(l-1-j+1)*(k-i+1);
                            if(narea>area)area=narea;
                            right=l-1;
                            flag=false;
                            break;
                        }
                    }
                    if(flag){
                        int narea=(right-j+1)*(k-i+1);
                        if(narea>area)area=narea;
                    }
                }
            }
        }
        cout<<area<<endl;
    }
}

問題 C: Bugs II

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 42  解決: 13
[提交] [狀態] [討論版] [命題人:外部匯入] [Edit] [TestData]

題目描述

在一根長度為L米的細線上有N只bugs,現在每隻bug的思維都特別簡單,他們要麼在細線上向左爬行,要麼在細線上向右爬行,而且爬行速度均為1米每秒。當兩隻bugs相撞時,他們會立即同時掉頭然後繼續爬行。他們碰撞是瞬間完成的(調轉方向時間可忽略)。現在給出一些bugs的開始位置和朝向,那麼在T秒時間後,每隻Bug的位置是哪呢?

輸入

多組輸入資料,每組資料第一行包含三個正整數L、T、N(1<=L<=100000,1<=N<=10000,1<=T<=10000),以空格分隔;接下來的N行中,每行輸入一個正整數P(0<=P<=N)和一個字元D,以空格分隔。其中P代表這隻bug的起始位置即距離細線左端的距離(單位:米),D代表這隻bug的起始爬行方向(L或R分別代表向左、向右爬行)。輸入以檔案尾結束。詳見樣例。

輸出

對於每組資料,輸出N行,按照輸入順序輸出每隻螞蟻的最終位置。如果在T秒後bug爬行超出了細線的邊界,則輸出outofline。每個輸出佔一行。每組輸出完成後再輸出一個空行。

樣例輸入

複製

10 2 3
4 R
5 L
8 R
10 1 4
1 R
5 R
3 L
10 R

樣例輸出

複製

3
6
10

2
6
2
outofline

提示

開始時不會有多隻在同一位置。

這是一道模擬題,可以將螞蟻看成相穿而過,只要控制好相對位置就行。

先記錄下來他們一開始的位置,然後根據離起點的遠近排序,然後根據相對位置輸出就行。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct node{
    int start,end,id;
    char dir;
}a[10005];
int cmp1(node x,node y){
    return x.start < y.start;
}
int cmp2(node x,node y){
    return x.id < y.id;
}
int temp[10005];
int main(){
    int l,t,n;
    char dir;
    while(scanf("%d%d%d",&l,&t,&n)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%d %c",&a[i].start,&a[i].dir);getchar();
            a[i].id = i;
        }
        sort(a,a+n,cmp1);
        for(int i=0;i<n;i++){
            if(a[i].dir == 'R') temp[i] = a[i].start + t;
            else temp[i] = a[i].start - t;
        }
        sort(temp,temp+n);
        for(int i=0;i<n;i++) a[i].end = temp[i];
        sort(a,a+n,cmp2);
        for(int i=0;i<n;i++){
            if(a[i].end < 0 || a[i].end > l) printf("outofline\n");
            else printf("%d\n",a[i].end);
        }
        printf("\n");
    }
    return 0;

問題 D: Bugs

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 45  解決: 15
[提交] [狀態] [討論版] [命題人:外部匯入] [Edit] [TestData]

題目描述

有兩隻Bugs在座標軸上,他們每個單位時間只能爬行一個單位長度,他們的爬行均為勻速運動。當兩隻Bugs相向爬行碰撞時,他們會各自掉頭繼續爬行,可以認為碰撞是瞬間發生。現在告訴你N只Bugs的爬行起點和方向,請問T時間後,向左和向右爬行的Bugs各有多少隻?

輸入

多組測試資料,每組資料先輸入兩個正整數 N (1<=N<=100) 和 T (1<=T<=1018),分別為代表Bugs數量以及爬行時間,接下來輸入N行,每行一個整數和一個字母。其中整數代表某隻Bug的開始位置,字母代表開始時候爬行的方向。

開始位置在[-1000,1000]範圍

爬行方向L和Rfe分別代表左和右

開始時候不會有任何兩隻Bugs在同一位置。

輸出

對於每組資料,輸出兩個整數,分別T代表時間後向左和向右的Bugs數量。以空格分隔。每組輸出佔一行。

樣例輸入

複製

2 2
-1 R
1 L

樣例輸出

複製

1 1

提示

開始時候兩隻bugs 分別在-1向右爬、1向左爬,1 單位時間後,他們在 0 位置碰撞並立即瞬間掉頭,然後分別向左和向右,從此之後他們不再碰撞,所以 2 單位時間後方向不變還是一個向左一個向右。

看成相穿而過就行。

#include<iostream>
using namespace std;
int main()
{
    int n; long long t;
    ios::sync_with_stdio(0);
    while(cin>>n>>t)
    {
        long long sum1 = 0, sum2 = 0;
        char c; int a;
        while(n--)
        {
            cin>>a>>c;
            if(c == 'R')
                sum2++;
            else
                sum1++;
        }
        cout<<sum1<<" "<<sum2<<endl;
    }
    return 0;
}

問題 E: 312的往事

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 22  解決: 11
[提交] [狀態] [討論版] [命題人:外部匯入] [Edit] [TestData]

題目描述

現在的ACM實驗室以前被稱為312,GGS在那裡度過了愉快的4年大學生活。最讓他難忘的就是和JiujieZhang一起取糖塊,每次我們親愛的孟老師總是買來一堆的糖塊,讓他們倆按照一定的規則取糖塊:
1、 GGS和JiujieZhang輪流從糖塊堆裡取糖塊,他們彼此可以看到另一個人取了多少, 也可以知道還剩下多少,兩個人都很聰明,不會做出錯誤的判斷。
2、 每個人取糖塊的數目必須是2或3或5個。
3、 輪到某一方取糖塊時不能棄權,最後不能按規則取到糖塊的人是輸的一方。

“誰先開始?”
這還用問嗎,當然是GGS了!
現在孟老師告訴他們糖塊總數,誰最後會贏呢,贏了的一方可是會得到所有的糖塊的奧!

輸入

資料有多組輸入,每組一個正整數n(1<=n<=100000),表示孟老師買回來的糖塊總數,輸入以檔案尾(EOF)結束。

輸出

誰最後可以得到所有的糖塊,如果是GGS,就輸出GGS,如果是JiujieZhang,就輸出JiujieZhang,不要忘記換行奧^_^

樣例輸入

複製

42
18468

樣例輸出

複製

JiujieZhang
GGS

一道博弈論,推就行發現7為一個週期

#include<stdio.h>
int main(void)
{
    int a[100003]={0,2,1,1,1,1,1};
    int i,n;
    for(i=7;i<100003;i++)
    {
        if((a[i-2]==2)||(a[i-3]==2)||(a[i-5]==2))
        a[i]=1;
        else
        a[i]=2;
    }
    while(scanf("%d",&n)!=EOF)
    {
        if(a[n]==1)
        {
        printf("GGS\n");
        }
        else
        printf("JiujieZhang\n");
    }
    return 0;
}

問題 F: 榮譽的氣球

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 29  解決: 14
[提交] [狀態] [討論版] [命題人:外部匯入] [Edit] [TestData]

題目描述

大學生程式設計競賽正在活人進行中…。比賽結束後,HaiLin和他的n個朋友們都AC了K個題,K>0,因此他們手中都有K個象徵榮譽的氣球,但不同的人可能得到了不同顏色的氣球。他們中的一些人想要某個顏色的氣球,於是他們做起了一個關於氣球的遊戲:在遊戲的每一輪中,只有一個人會給另一個人一個氣球。他們只顧著做遊戲了,但是忘了誰給誰氣球了,也忘了做了幾輪遊戲了。現在他們都知道自己手中有幾個氣球,你能幫他們計算出在開始的時候他們每人手中有幾個氣球嗎?

輸入

多組輸入資料,每組資料第一行輸入n和m,其中n代表HaiLin有幾朋友,m代表HaiLin手中的氣球個數。接下來一行輸入n個整數[x1,x2…xn],分別代表遊戲結束後HaiLin的n個朋友們的氣球個數,資料以空格分隔。輸入以檔案尾結束。1<=n<=100,0<=m<=20000,0<=xi<=20000。

輸出

對於每組資料,如果存在滿足上述條件的K,輸出K,否則輸出-1。每組輸出佔一行。

樣例輸入

複製

4 2
5 4 0 4
1 4
3

樣例輸出

複製

3
-1

提示

樣例分析:第3個朋友給第1個朋友一個氣球;第3個朋友給第4個朋友一個氣球;HaiLin給第2個朋友一個氣球;第3個朋友給第1個朋友一個氣球。

#include<stdio.h>
int main()
{
    int i, j, n, m, s;
    while(scanf("%d%d",&n,&m) != EOF)
    {
        s = m;
        for(i = 0; i < n; i ++)
        {
            scanf("%d",&j);
            s += j;
        }
        if(s % (n + 1) == 0 && s != 0)
            printf("%d\n",s / (n + 1));
        else
            printf("-1\n");
    }
  

問題 G: 單詞接龍

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 19  解決: 15
[提交] [狀態] [討論版] [命題人:外部匯入] [Edit] [TestData]

題目描述

單詞接龍是一個與我們經常玩的成語接龍相類似的遊戲,現在我們已知一組單詞,且給定一個開頭的字母,要求出以這個字母開頭的最長的“龍”(每個單詞都最多在“龍”中出現兩次),在兩個單詞相連時,其重合部分合為一部分,例如 beast和astonish,如果接成一條龍則變為beastonish,另外相鄰的兩部分不能存在包含關係,例如at和atide 間不能相連。

輸入

輸入的第一行為一個單獨的整數n(n<=20)表示單詞數,以下n行每行有一個單詞,輸入的最後一行為一個單個字元,表示“龍”開頭的字母。你可以假定以此字母開頭的“龍”一定存在.

輸出

只需輸出以此字母開頭的最長的“龍”的長度

樣例輸入

複製

5
at
touch
cheat
choose
tact
a

樣例輸出

複製

23

一道裸的搜尋題,只不過用字串解決

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
# include <cstring>
using namespace std;
string str[25];
int book[25];
int ans;
int n;
 
void dfs(string s)
{
    if(ans < s.size())
    {
        ans = s.size();
    }
    //特判斷開頭
    if(s == str[n])
    {
        for(int i = 0; i < n; i++)
        {
            if(s[0] == str[i][0])
            {
                book[i]++;
                dfs(str[i]);
            }
 
        }
    }
 
    for(int i = 0; i < n; i++)
    {
        string t;
        for(int j = 0; j < str[i].size(); j++)
        {
            t += str[i][j];
            int pos = s.rfind(t);
            if(pos != -1 && j + pos + 1 == s.size() && book[i]< 2)
            {
                book[i]++;
                dfs(s + str[i].substr(j + 1));
                book[i]--;
            }
        }
    }
}
 
 
int main(int argc,char *argv[])
{
    while(cin >> n)
    {
        ans = 0;
        memset(book, false, sizeof(book));
        for(int i = 0; i <= n; i++)
        {
            cin >> str[i];
        }
 
        dfs(str[n]);
        cout << ans << endl;
    }
 
    return 0;
}

問題 H: 推銷人員

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 39  解決: 9
[提交] [狀態] [討論版] [命題人:外部匯入] [Edit] [TestData]

題目描述

阿明是一名推銷員,他奉命到螺絲街推銷他們公司的產品。螺絲街是一條死衚衕,出口與入口是同一個,街道的一側是圍牆,另一側是住戶。螺絲街一共有 N 家住戶,第 i 家住戶到入口的距離為 Si米。由於同一棟房子裡可以有多家住戶,所以可能有多家住戶與入口的距離相等。阿明會從入口進入,依次向螺絲街的 X 家住戶推銷產品,然後再原路走出去。 阿明每走 1 米就會積累 1 點疲勞值,向第 i 家住戶推銷產品會積累 Ai點疲勞值。阿明是工作狂,他想知道,對於不同的 X,在不走多餘的路的前提下,他最多可以積累多少點疲勞值。

輸入

多組輸入資料。第一行有一個正整數 N,表示螺絲街住戶的數量。
接下來的一行有 N 個正整數,其中第 i 個整數 Si表示第 i 家住戶到入口的距離。資料保證 S1≤S2≤…≤Sn<10^8。
接下來的一行有 N 個正整數,其中第 i 個整數 Ai表示向第 i 戶住戶推銷產品會積累的疲勞值。資料保證 Ai<10^3。 輸入以檔案尾EOF結束。 
對於20%的資料,1≤N≤20;
對於40%的資料,1≤N≤100;
對於60%的資料,1≤N≤1000;
對於100%的資料,1≤N≤100000。

輸出

輸出 N 行,每行一個正整數,第 i 行整數表示當 X=i 時,阿明最多積累的疲勞值。每次輸出後需要回車換行。

樣例輸入

複製

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

樣例輸出

複製

15
19
22
24
25

12
17
21
24
27

提示

【樣例 1 說明】
X=1: 向住戶 5 推銷,往返走路的疲勞值為 5+5,推銷的疲勞值為 5,總疲勞值為 15。
X=2: 向住戶 4、5 推銷,往返走路的疲勞值為 5+5,推銷的疲勞值為 4+5,總疲勞 值為 5+5+4+5=19。
X=3: 向住戶 3、4、5 推銷,往返走路的疲勞值為 5+5,推銷的疲勞值 3+4+5,總疲 勞值為 5+5+3+4+5=22。
X=4: 向住戶 2、3、4、5 推銷,往返走路的疲勞值為 5+5,推銷的疲勞值 2+3+4+5, 總疲勞值 5+5+2+3+4+5=24。
X=5: 向住戶 1、2、3、4、5 推銷,往返走路的疲勞值為 5+5,推銷的疲勞值 1+2+3+4+5, 總疲勞值 5+5+1+2+3+4+5=25。

【樣例 2 說明】
X=1:向住戶 4 推銷,往返走路的疲勞值為 4+4,推銷的疲勞值為 4,總疲勞值 4+4+4=12。 X=2:向住戶 1、4 推銷,往返走路的疲勞值為 4+4,推銷的疲勞值為 5+4,總疲勞值4+4+5+4=17。
X=3:向住戶 1、2、4 推銷,往返走路的疲勞值為 4+4,推銷的疲勞值為 5+4+4,總疲勞值 4+4+5+4+4=21。
X=4:向住戶 1、2、3、4 推銷,往返走路的疲勞值為 4+4,推銷的疲勞值為 5+4+3+4, 總疲勞值 4+4+5+4+3+4=24。或者向住戶 1、2、4、5 推銷,往返走路的疲勞值為 5+5,推銷的疲勞值為 5+4+4+1,總疲勞值 5+5+5+4+4+1=24。
X=5:向住戶 1、2、3、4、5 推銷,往返走路的疲勞值為 5+5,推銷的疲勞值為 5+4+3+4+1, 總疲勞值 5+5+5+4+3+4+1=27。

來源/分類

NOIP 普及組 2015 

這道題可以用貪心的思想來做,也可以用優先佇列

# include <iostream>
# include <cstring>
# include <algorithm>
# include <cstdio>
# include <cstdlib>

using namespace std;

const int maxn = 100005;
struct node
{
    int s;
    int ai;
}s[maxn];

bool cmp(struct node a, struct node b)
{
    return a.ai > b.ai;
}

int main(int argc, char *argv[])
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int maxx = 0,maxi;
        for(int i = 0; i < n; i++)
        {
            scanf("%d",&s[i].s);
        }
        for(int i = 0; i < n; i++)
        {
            scanf("%d",&s[i].ai);
            if(maxx < s[i].s * 2 + s[i].ai)
            {
                maxx = s[i].s * 2 + s[i].ai;
                maxi = i;
            }
          //  s[i].sum = s[i].s + s[i].ai;
        }
        for(int i = 0; i < n; i++)
        {
            if(maxi != i &&s[i].s > s[maxi].s)
            {
                s[i].ai += (s[i].s - s[maxi].s) * 2;
                s[i].s = s[maxi].s;
            }
        }
        int ss = s[maxi].ai + s[maxi].s * 2;
        s[maxi].ai = 0;

        sort(s, s + n, cmp);

       // int maxx = 0;
        cout << ss << endl;
        for(int i = 0; i < n - 1; i++)
        {
            ss += s[i].ai;
            //maxx = max(maxx, s[i].s);
            printf("%d\n",ss);
        }
    }
    return 0;
}

問題 I: 湊錢

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 49  解決: 11
[提交] [狀態] [討論版] [命題人:外部匯入] [Edit] [TestData]

題目描述

某國的貨幣只有n種,它們的面值分別是value1,value2,...,valuen.現在我要買一件商品,它值cost元.我只能用這n種貨幣付款,並且每種貨幣我有任意枚。n種貨幣湊齊cost元嗎?如果能夠湊齊的話,最少需要多少枚貨幣呢?

輸入

每組測試資料佔2行。 
第一行有2個正整數n,cost(0<n<1000,0<cost<=10000)。 
第二行有n個整數,表示value1,value2,...,valuen(0<valuei<=10000)。

輸出

每組測試資料輸出它的結果,佔一行。如果能夠湊好,輸出需要最少的貨幣數;否則輸入"bad".

樣例輸入

複製

4 10
1 2 5 10
4 13
2 4 6 8

樣例輸出

複製

1
bad

可以用揹包的思想也可以用搜索做

,主要是要卡一個硬幣的數量和價值

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
using namespace std;
int a[10005];
int b[10005];
int main()
{
    int n, m;
    int x;
    int i;
    while(cin >> n >> m)
    {
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        for(int j = n; j >= 1; j--)
        {
            scanf("%d", &x);
            if(x > m)
                continue;
            for(i = x; i <= m; i++)
            {
                if(a[i] < a[i - x] + x)
                {
                    a[i] = a[i - x] + x;
                    b[i] = b[i - x] + 1;
                }
                else if(a[i] == a[i - x] + x)
                {
                    b[i] = min(b[i], b[i - x] + 1);
                }
            }
        }
        if(a[m] == m)
            printf("%d\n", b[m]);
        else
            printf("bad\n");
    }
    return 0;
}

問題 J: 洗衣服

時間限制: 5 Sec  記憶體限制: 128 MB
提交: 25  解決: 15
[提交] [狀態] [討論版] [命題人:外部匯入] [Edit] [TestData]

題目描述

小明是一個優秀的程式設計師,但他討於厭洗衣服,所以每次都用公共洗衣機洗衣服,但他帶衣服過去的時候總是發現沒有洗衣機空閒,需要等很久。作為一個優秀的程式設計師,小明黑入了洗衣房的監控,獲得了所有人去洗衣服的時刻,但他不知道,這些衣服什麼時候都洗完。請你幫助他寫一個程式解決這個問題。
為了方便計算,問題簡化為:n臺洗衣機,m個洗衣服任務,每個從xi開始持續45分鐘,求最短結束時間(假設從洗衣機裡取衣服放衣服不消耗時間,每臺洗衣機同一時間只能執行一個任務)。

輸入

第一行一個T(1≤T≤20)代表資料組數。
每組資料兩行:
第一行兩個整數n(1≤n≤100),m(1≤m≤1000)。n代表洗衣機臺數,m代表有m個洗衣任務。
第二行,m個整數(單調不下降),每個整數xi(0≤xi≤50,000)代表這個任務第xi分鐘加入排隊。

輸出

每組資料輸出一個整數代表所有任務的結束時間。

樣例輸入

複製

2
1 1
1
2 3
1 2 3

樣例輸出

複製

46
91

提示

對於第一個樣例,只有一臺洗衣機,在第一分鐘有一個洗衣任務,那麼這個洗衣任務在第(1+45)分鐘結束。
對於第二個樣例,有兩臺洗衣機,第一個任務交給1號洗衣機,第二個任務交給2號洗衣機,第二個任務在第(2+45)分鐘完成,在第(1+45)分鐘1號洗衣機完成洗衣任務並開始第三個任務,第三個任務在第(1+45+45)分鐘完成,所以答案為91。

來源/分類

這是一道模擬題,可以用佇列

# include <iostream>
# include <cstring>
# include <queue>

using namespace std;

struct node
{
    int rk;
}s[1005];

int main(int argc, char *argv[])
{
    int t;
    while(cin >> t)
    {
        while(t--)
        {
            memset(s, -1, sizeof(s));
            int n, m;
            cin >> n >> m;
            int flag;
            for(int i = 1; i <= m; i++)
            {
                cin >> s[i].rk;
            }
            queue<int> q;
            for(int i = 1; i <= n; i++)
            {
                if(s[i].rk != -1)
                {
                    int temp = s[i].rk;
                    q.push(temp);
                }
                else
                {
                    break;
                }
            }
            int temp, sum = 1;
            while(sum <= m )
            {
                temp = q.front();
                q.pop();

                if(temp + 45 < s[sum].rk)
                {
                    temp = s[sum].rk + 45;
                }
                else
                {
                    temp += 45;
                }
                q.push(temp);
                sum++;
            }
            cout << temp << endl;
        }
    }
    return 0;
}

問題 K: 涮羊肉

時間限制: 1 Sec  記憶體限制: 128 MB
提交: 51  解決: 17
[提交] [狀態] [討論版] [命題人:外部匯入] [Edit] [TestData]

題目描述

內蒙的羊由於生長的地域和氣候的不同,產出的羊肉區別於其它地區的羊肉,以鮮嫩味美著稱。
有一天,萊特跟瑞秋一起去內蒙吃涮羊肉,瑞秋往鍋裡下羊肉,萊特負責吃。
不同部位的肉要煮不同的時間,才能變得美味。萊特希望吃到最多的美味羊肉,但是萊特的手速不夠快,用m代表萊特的手速,每次下手撈羊肉後要過m秒才能再撈(每次只能撈一個)。
那麼用最合理的策略,萊特最多能吃到多少美味羊肉?

輸入

第一行一個T(1≤T≤120)代表資料組數
每組資料:
第一行兩個整數n,m(1≤n,m≤1000),其中n代表瑞秋往鍋裡下的羊肉個數,m代表萊特的手速。
接下來n行,每行兩個數x,y(1≤x,y≤1000)代表第x秒下的肉過y秒才能變得美味。

輸出

每個詢問輸出一個整數代表答案。

樣例輸入

複製

2
2 1
1 2
2 1
3 1
1 2
1 3
2 3

樣例輸出

複製

1
3

可以用標記的思想,把時間標記就可以過

# include <iostream>
# include <cstring>
# include <algorithm>

using namespace std;

int main(int argc, char *argv[])
{
    int t;
    while(cin >> t)
    {
        while(t--)
        {
            bool arr[2010] = {false};
            int n, m;
            cin >> n >> m;
            for(int i = 0; i < n; i++)
            {
                int x, y;
                cin >> x >> y;
                arr[x + y] = true;
            }

            int sum = 0;
            for(int i = 1; i <2010; i++)
            {
                if(arr[i])
                {

                    sum++;
                    i += m - 1;

                }


            }
            cout << sum   << endl;
        }
    }
    return 0;
}

問題 L: 統計數字

時間限制: 1 Sec  記憶體限制: 125 MB
提交: 47  解決: 20
[提交] [狀態] [討論版] [命題人:外部匯入] [Edit] [TestData]

題目描述

某次科研調查時得到了n個自然數,每個數均不超過1500000000(1.5*109)。已知不相同的數不超過10000個,現在需要統計這些自然數各自出現的次數,並按照自然數從小到大的順序輸出統計結果。

輸入

每組輸入資料包含n+1行;
第一行是整數n,表示自然數的個數;
第2~n+1行,每行一個自然數。
資料規模:
40%的資料滿足:1<=n<=1000;
80%的資料滿足:1<=n<=50000;
100%的資料滿足:1<=n<=200000,每個數均不超過1500000000(1.5*10^9)。

輸出

每組輸出包含m行(m為n個自然數中不相同數的個數),按照自然數從小到大的順序輸出。每行輸出兩個整數,分別是自然數和該數出現的次數,其間用一個空格隔開。

樣例輸入

複製

8
2
4
2
4
5
100
2
100

樣例輸出

複製

2 3
4 2
5 1
100 2

這道題可以取巧,先排序然後遍統計遍輸出

# include <iostream>
# include <cstring>
# include <algorithm>

using namespace std;

int main(int argc, char *argv[])
{
    int n;
    while(cin >> n)
    {
        long long int arr[200005];
        for(int i = 0; i < n; i++)
        {
            cin >> arr[i];
        }
        sort(arr, arr + n);

        int sum = 0, flag;
        for(int i = 0; i < n; i++)
        {
            if(i == 0)
            {
                flag = arr[i];
                sum++;
                continue;
            }
            if(flag != arr[i])
            {
                cout << flag << " " << sum << endl;
                sum = 0;
                flag = arr[i];
                sum++;
            }
            else
            {
                sum++;
            }
        }
         cout << flag << " " << sum << endl;
    }
    return 0;
}