CCF-CSP 201609 赛题训练

Posted ZSYL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF-CSP 201609 赛题训练相关的知识,希望对你有一定的参考价值。

CCF-CSP 201609 赛题训练

【CCF CSP-20160901】最大波动

题意概述

小明正在利用股票的波动程度来研究股票。小明拿到了一只股票每天收盘时的价格,他想知道,这只股票连续几天的最大波动值是多少,即在这几天中某天收盘价格与前一天收盘价格之差的绝对值最大是多少。

输入输出格式

输入的第一行包含了一个整数 n,表示小明拿到的收盘价格的连续天数。第二行包含 n 个正整数,依次表示每天的收盘价格。

输出一个整数,表示这只股票这 n 天中的最大波动值。

数据规模

2 ≤ n ≤ 1000 2\\le n\\le1000 2n1000,股票每一天的价格为 1 到 10000 之间的整数。

C++代码

#include <bits/stdc++.h>
using namespace std;
using gg = long long;
int main() 
    ios::sync_with_stdio(false);
    cin.tie(0);
    gg ni, last, cur, ans = 0;
    cin >> ni >> last;
    while (--ni) 
        cin >> cur;
        ans = max(ans, abs(cur - last));
        last = cur;
    
    cout << ans;
    return 0;

这个问题是一个求最值问题,把输入看作流,一边读入数据,一边计算处理,是一种好的做法,可以节省存储。

#include<bits/stdc++.h>
using namespace std;

int main() 
    int n, c, x, maxc = -1;
    cin >> n;
    cin >> c;
    for (int i = 1; i < n; i++) 
        cin >> x;
        maxc = max(maxc, abs(x-c));
        c = x;
    
    cout << maxc;

解法二:数组处理
从容易得分和习惯来说,把需要处理的数据读入到程序中的数组里,然后再进行处理,是一种更为常见的做法。要说这个习惯,其实是被教科书误导,教科书式的解法就那样。用数组,至少比较浪费存储。这里想问的是,假如n非常非常大,还能读到数组里再处理吗?

【CCF CSP-20160902】火车购票

题目

请实现一个铁路购票系统的简单座位分配算法,来处理一节车厢的座位分配。
假设一节车厢有20排、每一排5个座位。为方便起见,我们用1到100来给所有的座位编号,第一排是1到5号,第二排是6到10号,依次类推,第20排是96到100号。
购票时,一个人可能购一张或多张票,最多不超过5张。如果这几张票可以安排在同一排编号相邻的座位,则应该安排在编号最小的相邻座位。否则应该安排在编号最小的几个空座位中(不考虑是否相邻)。
假设初始时车票全部未被购买,现在给了一些购票指令,请你处理这些指令。

输入

输入的第一行包含一个整数n,表示购票指令的数量。
第二行包含n个整数,每个整数p在1到5之间,表示要购入的票数,相邻的两个数之间使用一个空格分隔。

输出

输出n行,每行对应一条指令的处理结果。 对于购票指令p,输出p张车票的编号,按从小到大排序。

输入样例

4 
2 5 4 2

输出样例

1 2
6 7 8 9 10
11 12 13 14
3 4

样例解释

购2张票,得到座位1、2。
购5张票,得到座位6至10。
购4张票,得到座位11至14。
购2张票,得到座位3、4。

提示
对于所有评测用例,1 ≤ n ≤ 100,所有购票数量之和不超过100。

算法思路

定义set[20][6]的数组,[i][0]存每一排已售卖的座位数,根据题意,如果购票指令P,有P+[i][0]<=5,则可以在这排安排座位,且座位连续。如果没有连续座位时,要从编号从小到大安排座位(不考虑连续)。

#include<bits/stdc++.h>
using namespace std;

int main() 
    int sets[20][6] = 0;
    int n, m;
    cin >> n;
    while (n--) 
        cin >> m;
        for (int i = 0; i < 20; i++)   // 连续查找20排
            if (sets[i][0] + m <= 5)   // 够连续分配
                for (int j = 1; j <= m; j++) 
                    cout << i*5+sets[i][0]+j << " ";  // 既然是从头开始连续分配,则直接定位空位置的坐标
                
                sets[i][0] += m;  // 更新已分配位置数量
                cout << endl;  // 换行
                m = 0;  // m清空,代表分配完毕
                break;  // 分配完毕
            
        
       
        // 若不能连续分配一排,则从低位开始分配
        for (int x = 0; m; x++)   // 直接从头遍历每一排
            if (sets[x][0] < 5)   // 该排还可以再分
                for (int j = sets[x][0]; j < 5; j++) 
                    cout << x*5+sets[x][0]+1 << " ";
                    sets[x][0]++;  // 已分配人数+1
                    if (--m == 0)  // --m 分完就结束
                    
                        cout << endl;
                        break;
                    
                
            
        
    
    return 0;

在大佬代码的基础上进行微改动。

#include<stdio.h>
int sets[20]; //每一排空缺的座位个数
int n,p;
int main()
	for(int j=0;j<20;j++) //初始时,每排5个座位都空缺
		sets[j]=5;
	
	scanf("%d",&n);
	
	for(int i=0;i<n;i++)
		scanf("%d",&p);
		for(int j=0;p && j<20;j++) //遍历所有排,查询是否有空缺
			if(sets[j]>=p) //如果空缺数大于等于p
				for(int k=1;k<=p;k++)
					printf("%d ",j*5+5-sets[j]+k);
				
				sets[j]-=p; //减去当前安排出去的座位
				p=0;
			
		
		//此时,要分配不相邻的座位,且任一排无法完全容纳这p个人
		for(int j=0;p && j<20;j++) //遍历所有排,查询是否有空缺
			if(sets[j]>0) //如果当前排的空缺数大于0
				for(int k=1;k<=sets[j];k++) //装满当前排
					printf("%d ",j*5+5-sets[j]+k);
				
				if(p>=sets[j]) //如果p大于等于当前排的空缺数,则先分配sets[j]个座位(在之后的排再分配p-set[j]个座位)
					p-=sets[j];
					sets[j]=0;
				
				else//反之全部分配
					sets[j]-=p;
					p=0;
				
			
		
		printf("\\n");
	
	return 0;

参考大佬代码2:https://blog.csdn.net/wingrez/article/details/82564259

加油!

感谢!

努力!

以上是关于CCF-CSP 201609 赛题训练的主要内容,如果未能解决你的问题,请参考以下文章

CCF-CSP 201604 赛题训练

CCF-CSP 201612 赛题训练

CCF-CSP 201709 赛题训练

CCF-CSP 201912 赛题训练

CCF-CSP 201703 赛题训练

CCF-CSP 202203 赛题训练