2018第一次校队集训题解

问题 A: 豆豆强的蛋糕店

时间限制: 1 Sec  内存限制: 128 MB
提交: 29  解决: 3
[提交] [状态] [讨论版] [
命题人:外部导入] [Edit] [TestData]

题目描述

豆豆强是一个人名,曾经是一名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
[提交] [状态] [讨论版] [
命题人:外部导入] [Edit] [TestData]

题目描述

小明最近看到一件艺术品,是由许多黑白方块组成的矩形图,但是并不是黑白相间的。小明希望找到一个最大的黑白相间的矩形。


 

输入

第一行输入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;
}

猜你喜欢

转载自blog.csdn.net/I_O_fly/article/details/84202982
今日推荐