2021-2013 CSP前两题汇总

本文详细解析了 CSP(Contest Software Problem)比赛历年来的部分试题,涵盖了灰度直方图、邻域均值、期末预测之安全指数、线性分类器、稀疏向量、报数、回收站选址等多个主题,通过 C++ 代码展示了各个问题的解决策略和思路,旨在帮助参赛者理解和提高算法能力。
摘要由CSDN通过智能技术生成

202104-1灰度直方图

在这里插入图片描述
样例输入:

4 4 16
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15

样例输出:

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

样例输入:

7 11 8
0 7 0 0 0 7 0 0 7 7 0
7 0 7 0 7 0 7 0 7 0 7
7 0 0 0 7 0 0 0 7 0 7
7 0 0 0 0 7 0 0 7 7 0
7 0 0 0 0 0 7 0 7 0 0
7 0 7 0 7 0 7 0 7 0 0
0 7 0 0 0 7 0 0 7 0 0

样例输出:

48 0 0 0 0 0 0 29
#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
int main() {
	int n, m, L;
	scanf("%d %d %d",&n,&m,&L);
	int i, j;
	int temp;
	int a[300];
	for (i = 0; i < 300; i++)
	{
		a[i] = 0;
	}
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < m; j++)
		{
			scanf("%d",&temp);
			a[temp]++;
		}
	}
	for (i = 0; i < L; i++)
		printf("%d ",a[i] );
	return 0;
}

202104-2 邻域均值

在这里插入图片描述
在这里插入图片描述
样例输入:

4 16 1 6
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15

样例输出:

7

样例输入:

11 8 2 2
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 7 0 0 0 7 0 0 7 7 0
7 0 7 0 7 0 7 0 7 0 7
7 0 0 0 7 0 0 0 7 0 7
7 0 0 0 0 7 0 0 7 7 0
7 0 0 0 0 0 7 0 7 0 0
7 0 7 0 7 0 7 0 7 0 0
0 7 0 0 0 7 0 0 7 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0

样例输出:

83

参考csdn:https://blog.csdn.net/qq_44668088/article/details/115943074?spm=1001.2014.3001.5501
二维前缀和
这样的代码用了四重循环会超时,用二维前缀和计算sum[i][j],在每次计算的时候直接计算sum,复杂度O(1),最终复杂度O(n²)
70分代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<stdlib.h>
using namespace std;
struct xiangsu {
    int l;//灰度
    int sum;//附近的点的灰度之和
    double avg;//所有元素灰度的平均值
    int n;//附近的元素个数
}xiang[610][610];
int main() {
    int n, L,r,t;//边长n,灰度L,大小r,阈值t
    int i, j,k,q;//循环变量
    int nums=0;
    scanf("%d %d %d %d",&n,&L,&r, &t);
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            xiang[i][j].n = 0;
            xiang[i][j].sum = 0;
        }
    }
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            scanf("%d", &xiang[i][j].l);            
            for (k = 0;k < n ;k++)
            {
                if (k >= i - r && k <= i + r)
                {
                    for (q = 0; q < n ; q++)
                    {
                        if (q >= j - r && q <= j + r)
                        {
                            xiang[i][j].n++;
                            xiang[k][q].sum += xiang[i][j].l;                          
                        }                        
                    }
                }              
                
            }
        }
    }
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            xiang[i][j].avg = xiang[i][j].sum * 1.0 / xiang[i][j].n;
            if (xiang[i][j].avg <= t)
                nums++;         
        }
    }
    printf("%d",nums);
    return 0;
}

sum[i][j] 存取的是从点(1,1)到点(i,j)这个区间内所有数值的和
可以推出sum[i][j] = sum[i-1][j]+sum[i][j-1] - sum[i-1][j-1]+A[i][j] 所以我们可以通过O ( n 2 ) O(n^2)O(n 2 )的时间复杂度来求得整个sum数组
如下图:绿+红-黄+蓝在这里插入图片描述

for(int i=1;i<=n;i++)
{
	for(int j=1;j<=n;j++)
	{
		sum[i][j] = sum[i-1][j]+sum[i][j-1] - sum[i-1][j-1]+A[i][j];
	}
}

求完二维前缀,下面以O(1)的复杂度求出(xmin,ymin)到(xmax,ymax)这个黄色区域内所有元素的和

area = sum[maxx][maxy] - sum[maxx][miny-1] - sum[minx-1][maxy] + sum[minx-1][miny-1];

100分代码:

#include<iostream>
using namespace std;
int n,L,r,t,ans=0;
int A[605][605]={0};
int sum[605][605]={0};
bool judgeBlack(int x,int y)
{
	int maxx = min(n, x+r);
	int maxy = min(n, y+r);
	int minx = max(1, x-r);
	int miny = max(1, y-r);
	int s = sum[maxx][maxy] - sum[maxx][miny-1] - sum[minx-1][maxy] + sum[minx-1][miny-1];
	int count = (maxx-minx+1)*(maxy-miny+1);
	double test = s/(double)count;
	return test<=t;
}
int main()
{
	cin>>n>>L>>r>>t;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>A[i][j];
			sum[i][j] = sum[i-1][j]+sum[i][j-1] - sum[i-1][j-1]+A[i][j];
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
			if(judgeBlack(i,j))
				ans++;
	}
	cout<<ans;
	return 0;
}

202012-1期末预测之安全指数

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
int main() {
	int n, w, score;
	int i;
	int sum = 0;
	scanf("%d",&n);
	for (i = 0; i < n; i++)
	{
		scanf("%d %d",&w,&score);
		sum += w * score;
	}
	if (sum >= 0)
		printf("%d", sum);
	else
		printf("0");
	return 0;
}

202012-2 期末预测之最佳阈值

在这里插入图片描述

样例输入:

6
0 0
1 0
1 1
3 1
5 1
7 1

样例输出:

3

样例输入:

8
5 1
5 0
5 0
2 1
3 0
4 0
100000000 1
1 0

样例输出:

100000000

参考csdn:https://blog.csdn.net/qq_45985728/article/details/114903481
二重循环排序,这样会超时,使用邻域均值,一维前缀和
70分答案:

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cctype>
#include<string>
#include<algorithm>
using namespace std;
const int maxn = 100010;
struct student {
    int y;
    int result;
    int predict;

}stu[maxn];
bool cmp(student a, student b)
{
    if (a.predict != b.predict) return a.predict > b.predict;
    else return a.y > b.y;
}
int main() {
    int m, i;
    int j;
    scanf("%d",&m);
    for (i = 0; i < m; i++)
    {
        scanf("%d %d",&stu[i].y,&stu[i].result);
        stu[i].predict = 0;
    }
    for (i = 0; i < m; i++)
    {
        for(j=0;j<m;j++)
            if (stu[j].y>=stu[i].y&& stu[j].result==1|| stu[j].y < stu[i].y && stu[j].result == 0)
            {
                stu[i].predict++;
            }
    }
    sort(stu,stu+m,cmp);
    printf("%d",stu[0].y);
    return 0;
}

70分答案-结构体版
这题的细节真的好多呀,全部思路已经和下面的100分一模一样了,但是还是超时了!!!
看来不仅思路要对,还得选正确的数据结构啊!orz
这题耗时我猜是因为用了结构体,不断在结构体里面赋值排序这些还调用cmp函数比较耗时
100分里面直接用sort自带的给pair排序,然后pre0和rear1都是直接用数组存的,估计读写较快,又是亿个小细节~

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
struct student {
	int y;
	int result;
	int pre;//前面的0
	int rear;//后面的1
	int sum;
}stu[210];
bool cmp(student a, student b)
{
	if (a.y != b.y)
		return a.y < b.y;
	else
		return a.result < b.result;
}
bool cmp1(student a, student b)
{
	if (a.sum != b.sum)
		return a.sum > b.sum;
	else
		return a.y > b.y;
}
int main() {
	int m;
	int i;
	int j;
	int sum = 0;
	int ans;//最后的结果
	scanf("%d", &m);
	for (i = 0; i < m; i++)
	{
		scanf("%d %d", &stu[i].y, &stu[i].result);
		stu[i].sum = 0;
		stu[i].pre = 0;
		stu[i].rear = 0;
	}

	sort(stu, stu + m, cmp);
	if (stu[0].result == 0)
		stu[0].pre = 1;
	else
		stu[0].pre = 0;
	for (i = 1; i < m; i++)
	{
		if (stu[i].result == 0)
		{			
			stu[i].pre = stu[i - 1].pre + 1;//下一个阈值的pre为1
		}
		else
		{
			stu[i].pre = stu[i - 1].pre;//下一个阈值的pre为0
		}
	}
	if(stu[m-1].result==1)
		stu[m-1].rear = 1;
	else
		stu[m-1].rear = 0;
	for (i = m - 2; i >= 0; i--)
	{
		if (stu[i].result == 1)
		{
			stu[i].rear = stu[i + 1].rear + 1;//上一个阈值的rear为2
		}
		else//等于0,那么
		{
			stu[i].rear = stu[i + 1].rear;//上一个阈值的rear为0
		}
	}
	/*for (i = 0; i < m; i++)
	{
		stu[i].sum=stu[i].rear+stu[i-1].pre;
		printf("i=%d,y=%d,pre=%d,last=%d,sum=%d\n",i,stu[i].y,stu[i].pre,stu[i].rear,stu[i].sum);
	}*/
	sum = stu[0].rear; 
	ans = stu[0].y;
	for (i = 1; i < m; i++)
	{
		if (stu[i].y == stu[i - 1].y)//这种情况一定是后一个比前一个多1,但是不可取,因为前一个是相等的,后一个的统计无效,或者后一个和前一个一样,(无需统计,在前面统计过了),
			continue;//只要看前一个就可以了,continue直接跳过当前的循环,进入下一个循环
		if (sum <= stu[i - 1].pre + stu[i].rear)//注意要等于,因为这样才能取到序号最大的
			sum = stu[i - 1].pre + stu[i].rear, ans = stu[i].y;
	}
	printf("%d", ans);
	return 0;
}

100分答案pair版:
注意sort对pair进行排序的时候,首先对第一数排序,如果first相同,就对second排序

#include<iostream>
#include<algorithm>
using namespace std;
pair<int,int> pii[100005];      //pair数组储存信息,每个pair存储一个同学的y和result
int pre0[100005];               //记录该位置及前面的result为0的个数(前缀和)
int rear1[100005];              //记录该位置及后面的result为1的个数(后缀和)
int k = -1,ma = 0;              //k用来记录最佳阈值,ma用来存储最佳阈值对应的预测成国公数目
int main(){
    int m;
    cin>>m;                     //输入m
    pii[0] = pair<int,int>(-1,-1);
    for(int i = 1;i <= m;++i)   //初始化pii数组
        cin>>pii[i].first>>pii[i].second;
    sort(pii + 1,pii + 1 + m);  //将所有学生信息按照阈值从小到大排序,方便后续前缀后缀和的操作
    for(int i = 1;i <= m;++i)            //记录前缀0个数
        if(pii[i].second == 0)
            pre0[i] = pre0[i - 1] + 1;
        else
            pre0[i] = pre0[i - 1];
    for(int i = m;i >= 1;--i)           //记录后缀1个数
        if(pii[i].second == 1)
            rear1[i] = rear1[i + 1] + 1;
        else
            rear1[i] = rear1[i + 1];
    for(int i = 1;i <= m;++i){          //最终处理
        if(pii[i].first == pii[i - 1].first)
            continue;                   //如果有阈值相同的情况,那么在相同区间的第一个位置统计了,直接跳过
        if(ma <= pre0[i - 1] + rear1[i])//更新k和ma
            ma = pre0[i - 1] + rear1[i],k = pii[i].first;
    }
    cout<<k;
    return 0;
}

202009-1 称检测点查询

常规题目

202009-2 风险人群筛查

常规题目,这题竟然没有一点套路,好感人

202006-1 线性分类器

1.用sum计算求得的函数值,如果两个点的函数值相乘大于0,说明这两个点属于同一类,重点是if函数的判断,因为int类型只有10的9次方,而题目最大可以到10的12次方,所以需要用long long来存储sum
2.在判断两个点的sum是否同号时,不要用相乘的结果大于零判断,因为这样一样的会让结果越界,所以直接判断即可

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<stdlib.h>
using namespace std;
const int maxn = 1010;
struct dian{
	int x;
	int y;
    char type;
	long long int sum;
}dia[maxn];
int main() {
	int n, m;
	int i,j;
	int num1, num2, num3;
	int flag;
	scanf("%d %d",&n,&m);
	for (i = 0; i < n; i++)
	{
		scanf("%d %d %c",&dia[i].x,&dia[i].y,&dia[i].type);
	}	
	for (i = 0; i < m; i++)
	{
		flag = 1;
		scanf("%d %d %d",&num1,&num2,&num3);
		for (j = 0; j < n; j++)
		{
			dia[j].sum = num1 + num2 * dia[j].x + num3 * dia[j].y;	
		}
		for (j = 0; j < n-1; j++)
		{
			if (((dia[j].sum >0&& dia[j + 1].sum > 0|| dia[j].sum < 0 && dia[j + 1].sum < 0) && (dia[j].type != dia[j + 1].type ))|| ((dia[j].sum >0&& dia[j + 1].sum < 0 || dia[j].sum <0 && dia[j + 1].sum > 0)&&( dia[j].type == dia[j + 1].type)))//重点是这个判断
			{
				flag = 0;
				break;
			}		
		}
		if (flag == 0)
			printf("No\n");
		else
			printf("Yes\n");
	}
	return 0;
}

202006-2 稀疏向量

在这里插入图片描述
样例输入

10 3 4
4 5
7 -3
10 1
1 10
4 20
5 30
7 40

样例输出

-20

1、一开始用hash表来表示在v中的下标有没有出现过,但是后来n取到了10的9次方,取hashtable[1000000010],实在是太大了,程序会编译不通过
2、使用map来建立两个元素之间的映射关系,当向量v中出现新的下标和元素值的时候,就把<下标,元素值>记录到map中
3、在向量u输入的时候mp.find(向量u的下标),如果该下标出现过,那么计算sum+=元素1*元素2,这里注意元素1和元素2都要取long long int ,因为从测试用例4之后元素的乘积可能大于Int的范围。

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<map>
#include<utility>
using namespace std;
map<long int,long int> mp;
int main() {
	int n, a, b;
	int i;
	long long int sum = 0;
    long long int temp1, temp2;
	map<long int,long int>::iterator it;
	scanf("%d %d %d",&n,&a,&b);
	for (i = 1; i <=a; i++)
	{
		scanf("%lld %lld", &temp1, &temp2);
		mp.insert(pair<long int, long int>(temp1, temp2));
	}
	for (i = 1; i <= b; i++)
	{
		scanf("%lld %lld", &temp1, &temp2);
		it = mp.find(temp1);
		if (it!= mp.end())
			sum += it->second * temp2;		
	}
	printf("%lld",sum);
	return 0;
}

201912-1 报数

这题需要审题n到底是什么,一开始没有看好题目,花了好长时间

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<map>
#include<utility>
using namespace std;
//此函数用来判断n是否需要被跳过
int judge(int n)
{
	int flag = 1;//
	int temp;
	if (n % 7 == 0)
		flag = 0;
	else
	{
		while (n != 0)
		{
			temp = n % 10;
			if (temp == 7)
			{
				flag = 0;
				break;
			}
			n /= 10;
		}
	}
	return flag;
}
int main() {
	int n;
	int a[5] = {0};
	int lun=1;//表示第几轮
	int num=1;
	scanf("%d",&n);//取到n的值
	while(n!=0)	
	{
		if (judge(num))//正常的数
		{					
			n--;//剩下还可以报出的数-1
		}
		else
		{
			a[lun % 4]++;				
		}		
		num++;
		lun++;//要注意不管是正常的数还是跳过的数,都算一轮;
	}
	printf("%d\n%d\n%d\n%d\n", a[1], a[2], a[3], a[0]);	
	return 0;
}

201912-2 回收站选址

在这里插入图片描述

1、这题一开始想用map映射来存储坐标x和坐标y,后来发现Map只能做到一一映射,也就是它的一个横坐标只能对应一个纵坐标,所以不能同时存下(2,1)与(2,2),所以还是老老实实用结构体来存储,因为题目说n最多是1000,所以结构体还不算很大
2、我发现csp的第二题只要复杂度控制在n²内就不会超时了,20年12月的除外,注意这个题目是怎么判断的,首先十字架坐标垃圾堆4个都要有,然后再对角线坐标垃圾堆的个数决定得分。
但是如果先判断十字架坐标满足,然后再遍历一遍找对角线的格数,复杂度变为2n²了
3、所以不管这个点符不符合,都先把对角线垃圾堆的个数记录下来,如果十字架格数为4了,直接赋值,让时间少了一半
4、最后一点是怎么判断十字架垃圾堆和对角线垃圾堆。一开始我使用逐个对比x和y坐标的方法,发现这样代码冗长,可以直接计算两者x和y坐标的差的绝对值,如果绝对值之和=1,表示是十字架垃圾堆,绝对值之和=2,并不能表示是对角线垃圾堆,因为有可能是(10,10)和(12,10),这个时候要看横纵坐标差的绝对值分别为1!一开始没有注意到,只能过两个测试点。
5、这题很巧妙的让坐标都小于10的9次方,所以不管是正负数加或者减都不会超过Int的范围,感动

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<map>
#include<utility>
using namespace std;
struct dian {
	int x;
	int y;
}dia[1010];
int main() {
	int n;	
	int i,j;
	int score;
	int scores[5] = { 0 };
	int flag;
	scanf("%d",&n);//取到n的值
	for (i = 0; i < n; i++)
		scanf("%d %d",&dia[i].x,&dia[i].y);
	for (i = 0; i < n; i++)
	{		
		score = 0;
		flag = 0;
		for (j = 0; j < n; j++)
		{
			if (abs(dia[j].x - dia[i].x)+abs(dia[j].y - dia[i].y)== 1)
			{
				flag ++; 				
			}
			//这里要注意
			else if (abs(dia[j].x - dia[i].x)==1&&abs(dia[j].y - dia[i].y) == 1)
			{
				score++;				
			}			
		}
		if (flag == 4)
		{
			scores[score]++;
		}

	}
	for (i = 0; i <= 4; i++)
		printf("%d\n",scores[i]);	
	return 0;
}

201909-1 小明种苹果

这题一开始在for循环后面加了括号,找了半天没找出来,又是亲爱的小伙伴帮我找出来的,菜鸡如我orz

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<map>
#include<utility>
using namespace std;
const int maxn = 1010;
struct Tree {
	int ori;
	int sum;//摘掉的苹果总数
}tree[maxn];
int main() {
	int n,m;
	int i,j;
	int temp;
	int T= 0;
	int k = 0;
	scanf("%d %d",&n,&m);
	for (i = 0; i < n; i++)
	{		
		scanf("%d",&tree[i].ori);
		T += tree[i].ori;
		tree[i].sum = 0;
		j = 0;
		for (j = 0; j < m; j++)
		{
			scanf("%d",&temp);
			tree[i].sum += temp;
		}
		T += tree[i].sum;
		if (tree[i].sum < tree[k].sum)
			k = i;
	}
	printf("%d %d %d",T,k+1,-tree[k].sum);
	return 0;
}

201909-2 小明种苹果(续)

这题有一点,就是一棵树可能小明统计了很多次果子数量,当一棵树掉很多次果子的时候,D也只是+1,所以需要用flag来判断,不能每次掉果子都让D+1

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<map>
#include<utility>
using namespace std;
const int maxn = 1010;
int main() {
	int n,m;
	int i,j;
	int temp;
	int T[maxn] = {0};//表示现在第i棵树上还有几颗果子
	int a[maxn] = { 0 };//记录第i棵树有没有掉果子
	int D = 0;
	int E = 0;	
	int TT=0;
	int flag;
	scanf("%d",&n);
	for (i = 0; i < n; i++)
	{		
		flag = 0;
		scanf("%d", &m);
		scanf("%d", &T[i]);		
		for (j = 0; j < m-1; j++)
		{
			scanf("%d",&temp);
			if (temp <= 0)//进行了疏果操作
			{
				T[i] += temp;
			}				
			else//统计了当前树上的果子数量
			{			
				if (T[i] > temp)//说明掉了果子
				{
					T[i] = temp;
					flag = 1;
					a[i] = 1;//记录这颗苹果树的果子掉了
				}
			}				
		}	
		if (flag == 1)
			D++;
	}
	for (i = 0; i < n; i++)
	{
		if (a[i % n] == 1 && a[(i + 1) % n] == 1 && a[(i + 2) % n] == 1)
			E++;
		TT += T[i];
	}
	printf("%d %d %d",TT,D,E);
	return 0;
}

201903-1 小中大

这题说最多保留一位小数四舍五入这些,本来输入的是整数,最多也就.5的小数啊,中间格式化输出%g或者%f的时候总是报错,拿90或者70分

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<map>
#include<utility>
using namespace std;
const int maxn = 100010;
int a[maxn] = { 0 };
int main() {
	int n;
	int i;
	scanf("%d",&n);
	for (i = 0; i < n; i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a, a + n);
	int max, min, mid;
	max = a[n-1];
	min = a[0];	
	if (n & 1)
	{
		mid = a[n / 2];
		printf("%d %d %d", max, mid , min);
	}			
	else
	{
		mid = a[n / 2] + a[n / 2 - 1];
		if (mid & 1)
			printf("%d %d.5 %d", max, mid / 2, min);
		else
			printf("%d %d %d", max, mid / 2, min);	}		
	return 0;
}

201903-2 二十四点

在这里插入图片描述

1、首先不能用字符存储乘号×,这样会输出?如下:
在这里插入图片描述
所以选择用字符串存储,在栈中计算。
另外当出现减法的时候将它转换为加法,让j++,这个想法也很巧妙

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;

int n;
char str[10];

stack<int> num;//数字栈
stack<char> sign;//符号栈

int main() {
	scanf("%d", &n);
	getchar(); //读取留在缓冲区的换行符
	for (int i = 0; i < n; i++) {
		scanf("%s",str);

		while (!num.empty()) num.pop();	//清空栈
		while (!sign.empty()) sign.pop();

		int j = 0;
		while (j < strlen(str)) {
			if (str[j] > '0' && str[j] <= '9') {
				num.push(str[j] - '0');
			}
			else {
				if (str[j] == '+') {
					sign.push('+');
				}
				else if (str[j] == '-') { //将减法转换成加法 
					num.push((str[j + 1] - '0') * (-1));
					sign.push('+');
					j++;
				}
				else if (str[j] == 'x') { //直接计算乘法 
					int lhs = num.top();
					num.pop();
					num.push(lhs * (str[j + 1] - '0'));
					j++;
				}
				else if (str[j] == '/') { //直接计算除法 
					int lhs = num.top();
					num.pop();
					num.push(lhs / (str[j + 1] - '0'));
					j++;
				}
			}
			j++;
		}

		while (!sign.empty()) { //计算剩余的加法 
			int rhs = num.top();
			num.pop();
			int lhs = num.top();
			num.pop();
			sign.pop();
			num.push(lhs + rhs);
		}

		int ans = num.top();
		if (ans == 24) printf("Yes\n");
		else printf("No\n");

	}

	return 0;
}

201812-1 小明上学

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
int main() {
	int r, y, g;
	scanf("%d %d %d",&r,&y,&g);
	int n;
	int i;
	scanf("%d", &n); 

	int sum = 0;//上学的总时长
	int temp1, temp2;
	for (i = 0; i < n; i++) {
		scanf("%d %d",&temp1,&temp2);
		if (temp1 == 0)
			sum += temp2;
		else if (temp1 == 1)//如果遇到红灯,等待
			sum += temp2;
		else if (temp1 == 2)//雨打黄德国,等待黄灯+红灯
			sum +=  temp2 + r;
		else//遇到绿灯,直接通行
			;
	}
	printf("%d", sum);
	return 0;
}

201812-2小明放学

在这里插入图片描述

这题做好分类讨论就可以啦,注意后面4个测试单要取到long long int才可以

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
int main() {
	int r, y, g;
	scanf("%d %d %d",&r,&y,&g);
	int n;
	int i;
	scanf("%d", &n); 

	long long int sum = 0;//上学的总时长
	long long int temp1, temp2;
	int t = 0;//表示到当前路口时已经过去的时间
	for (i = 0; i < n; i++)
	{
		scanf("%lld %lld",&temp1,&temp2);
		if (temp1 == 0)
		{
			sum += temp2;//总时长+			
		}
		else
		{
			temp2 -= sum;//一开始的时长减去已经过去的时长
			if (temp1 == 1)//表示一开始是红灯
			{
				
				if(temp2 >=0)//说明现在还是红灯,等过这个绿灯就可以了
				sum += temp2;
				else//说明已经变灯了
				{
					temp2 = -temp2;//从绿灯开始算,又过去了temp2秒					
					temp2 %= r + y + g;//算在一个周期里面
					if (temp2 <= g)
						;//直接通过
					else //是黄灯或者红灯
						sum += (g + y + r - temp2);//等红灯的时间
				}
			}
			else if (temp1 == 2)//表示当前是黄灯
			{
				if (temp2 >= 0)//说明现在还是黄灯,等过这个黄灯+红灯就可以了
					sum += temp2 + r;
				else
				{
					temp2 = -temp2;
					temp2 %= r + y + g;//算在一个周期里面
					if (temp2 <= r)//说明现在是红灯
						sum += r - temp2;
					else if (temp2 <= r + g)
						;//绿灯,直接通过
					else//黄灯
						sum += (r + g + y - temp2) + r;//等黄灯的时间+等红扽的时间
				}

			}
			else//表示当前是绿灯
			{
				if (temp2 >= 0)//说明现在还是绿灯,
					;
				else
				{
					temp2 = -temp2;
					temp2 %= r + y + g;//算在一个周期里面
					if (temp2 <= y + r)//现在是黄灯
						sum += y + r - temp2;
					else//说明又到了绿灯
						;//通过
				}
			}
		}
	}
	printf("%lld", sum);
	return 0;
}

201809-1 卖菜

这题需要注意第二天的价格要再开一个数组存放,不然之后算平均的时候价格已经改变了。

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int maxn = 1010;
int shop1[maxn] = { 0 };
int shop2[maxn] = { 0 };
int main() {
	int n;
	scanf("%d",&n);
	int i;
	for (i = 0; i < n; i++)
	{
		scanf("%d",&shop1[i]);
	}
	
	for (i = 1; i < n - 1; i++)
	{
		shop2[i] = (shop1[i - 1] + shop1[i] + shop1[i + 1])/3;
	}
	shop2[0] = (shop1[0] + shop1[1]) / 2;
	shop2[n-1]= (shop1[n-1] + shop1[n-2]) / 2;
	for (i = 0; i < n; i++)
	{
		printf("%d ",shop2[i]);
	}
	return 0;
}

201809-2 买菜

考察结构体存放,没有坑,复杂度n²

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int maxn = 1000010;
struct hash {
	int id;
	int biaoji;
}hashtable[maxn];
int main() {
	int n;
	scanf("%d",&n);
	int i,j;
	int temp1, temp2;
	int sum=0;
	//首先初始化
	for (i = 0; i < n; i++)
	{
		hashtable[i].id = hashtable[i].biaoji = 0;
	}

	for (i = 1; i <=n; i++)
	{
		scanf("%d %d",&temp1,&temp2);
		for (j = temp1; j <= temp2; j++)
		{
			hashtable[j].id = 1;
			hashtable[j].biaoji = i;//同一个时间段的标记相同
		}
	}
	for (i = 1; i <= n; i++)
	{
		scanf("%d %d", &temp1, &temp2);
		for (j = temp1; j < temp2; j++)
		{
			if (hashtable[j].id == 1&&hashtable[j+1].id==1&&hashtable[j].biaoji==hashtable[j+1].biaoji)
				sum++;
		}
	}
	printf("%d",sum);
	
	return 0;
}

201803-1 跳一跳

简单的判断

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;

int main() {
	int n;
	int scores = 0;
	int score=1;//每一局的得分
	while (scanf("%d", &n), n != 0)
	{
		if (n == 1)
			score = 1;
		else
		{
			if (score == 1)
				score = 2;
			else
				score += 2;
		}			
		scores += score;		
	}
	printf("%d",scores);
	return 0;
}

201803-2 碰撞的小球

在这里插入图片描述

1、注意最后输出小球的时候要按照当时输入的顺序输出,所以结构体里面要加上一个id来标识
2、sort排序的时候注意下标
3、定义flag=1或者=-1来表示是向右还是向左走,下一个时刻的位置=上一个时刻的位置+flag
4、这题很贴心的说了没有三个小球同时相撞,不然要搜索三个甚至更多在同一坐标的小球复杂度又会上去了
5、老问题,复杂度控制在n²就Ok,
6、感觉这两年的题目都是考一些分类,思路理清楚就好了

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
using namespace std;
struct Ball {
	int a;//表示小球的位置
	int flag;//表示小球的方向1表示向右,-1表示向左
	int id;
}ball[110];
bool cmp1(Ball a,Ball b)
{
	if (a.a != b.a)
		return a.a < b.a;
	else if(a.flag!=b.flag)return a.flag > b.flag;
	else return a.id < b.id;
}
bool cmp2(Ball a, Ball b)
{
	return a.id < b.id;
}
int main() {
	int n,L,t;
	scanf("%d %d %d",&n,&L,&t);
	int i;
	int j;
	for (i = 1; i <= n; i++)
	{
		scanf("%d",&ball[i].a);
		ball[i].flag = 1;
		ball[i].id = i;
	}
	for (j = 1; j <= t; j++)//t秒之后
	{
		//时刻j
		sort(ball+1, ball + n+1, cmp1);		
		//下面改变方向
		//首先考虑有没有在位置0和位置L的
		for (i = 1; i <= n; i++)
		{
			if (ball[i].a == 0 || ball[i].a == L)
				ball[i].flag *= -1;
		}
		//然后考虑一般情况
		for (i = 1; i < n; i++)
		{
			if (ball[i].a == ball[i + 1].a && ball[i].flag != ball[i + 1].flag)
			{
				swap(ball[i].flag, ball[i + 1].flag);
				i++;//题目保证了不会有三个小球同时相撞
			}
		}
		//下面移动距离
		for (i = 1; i <= n; i++)
		{
			ball[i].a += ball[i].flag;
		}		
	}
	sort(ball + 1, ball + n + 1, cmp2);
	for (i = 1; i <= n; i++)
	{
		printf("%d ", ball[i].a);
	}
	return 0;
}

201712-1 最小差值

基础题

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
using namespace std;
int a[1010] = { 0 };
int main() {
	int n;
	int min;
	int i;
	int temp;
	scanf("%d", &n);
	for (i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
	}
	sort(a, a + n);
	min = a[1] - a[0];
	for (i = 1; i < n-1; i++)
	{
		temp = a[i + 1] - a[i];
		if (temp < min)
			swap(temp, min);
	}
	printf("%d",min);
	return 0;
}

201712-2 游戏

一样是绕逻辑的一道题目

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
using namespace std;
int hashtable[1010] = { 0 };
int main() {
	int n;
	int k;
	scanf("%d %d",&n,&k);
	int i=0;//表示当前报数的小朋友编号
	int nums = 1;//当前报的数字
	int num=n;//剩下的小朋友的个数;
	for(i=0;num>1;)//
	{
		i++;//小朋友编号+1
		
		if (hashtable[i % n] == 1)//如果当前小朋友已经被淘汰了
			continue;
		else
		{
			//printf("当前%d号小朋友报数%d\n", i % n, nums);
			if (nums % k == 0 || nums % 10 == k)
			{
				hashtable[i % n] = 1;
				num--;
				//淘汰
			}				
		}	
		nums++;
	}
	for (i = 0; i < n; i++)
	{
		if (hashtable[i] == 0)
			break;
	}
	if (i % n == 0)
		printf("%d",n);
	else
	printf("%d",i%n);
	return 0;
}

201709-1打酱油

基础题

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
using namespace std;
int main() {
	int n;
	scanf("%d",&n);
	int sum = 0;
	if (n >= 50)
		sum += n / 50 * 7;
	n = n - n / 50 * 50;
	if (n >= 30)
		sum += n / 30 * 4;
	n = n - n / 30 * 30;
	sum += n / 10;
	printf("%d",sum);
	return 0;
}

201709-2 公共钥匙盒

在这里插入图片描述

同样是结构体+逻辑,涉及排序
一开始我想要定老师为一个结构体,后来发现应该把取钥匙或者还钥匙的操作定义为一个结构体
1、当换完钥匙之后立即break
2、注意结构体排序函数cmp的编写

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 2010;
struct yaoshi {
	int id;//钥匙的编号
	int time;//借或者还的时间
	int flag;//表示是换钥匙还是取钥匙,flag=-1表示取钥匙,flag=1表示还钥匙
}Yao[maxn];
bool cmp(yaoshi a, yaoshi b)
{	
	if (a.time != b.time)//首先按照时间顺序排序
		return a.time < b.time;
	else if (a.flag != b.flag) return a.flag > b.flag;//如果时间相同,就先换钥匙,再取钥匙
	else//如果还的时间相同,就按照id大小还钥匙
		return a.id < b.id;
}
int main() {
	int n,k;
	int i;
	int j;
	int id;
	int a[maxn] = {0};//0表示没有钥匙在上面,n表示n号钥匙在上面
	scanf("%d %d",&n,&k);
	//初始化钥匙盒
	for (i = 1; i <= n; i++)
	{
		a[i] = i;
	}
	//初始化钥匙,并排序
	for (i = 1; i <=2*k; i+=2)//一共2k个操作
	{
		scanf("%d",&id);
		scanf("%d %d", &Yao[i].time, &Yao[i+1].time);
		Yao[i].id = Yao[i+1].id = id;
		Yao[i + 1].time += Yao[i].time;
		Yao[i].flag = -1;//取钥匙
		Yao[i+1].flag = 1;//还钥匙
	}	
	sort(Yao+1, Yao + 2*k+1, cmp);
	for (i = 1; i <=2*k; i++)//遍历2*k次钥匙操作
	{
		if (Yao[i].flag == -1)//如果是取钥匙
		{
			for (j = 1; j <= n; j++)
				if (a[j] == Yao[i].id)
				{
					a[j] = 0;
					break;
				}					
		}
		else//还钥匙
		{
			for (j = 1; j <= n; j++)
				if (a[j] == 0)
				{
					a[j] = Yao[i].id;//这里注意还完钥匙,不用再寻找后面空的钥匙位了
					break;
				}					
		}	
		
	}
	for (j = 1; j <= n; j++)
		printf("%d ", a[j]);
	return 0;
}

201703-1 分蛋糕

基础题

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 2010;
int main() {
	int n, k;
	scanf("%d %d",&n,&k);
	int num = 0;//最终分到蛋糕的数量
	int i;
	int temp;
	int sum = 0;
	for (i = 0; i < n; i++)
	{
		scanf("%d", &temp);
		sum += temp;
		if (sum >= k)
		{
			num++;
			if (i == n - 1)//如果是最后一块蛋糕了,那么sum不需要清零了
				break;
			sum = 0;
		}
	}
	if (sum < k)//如果蛋糕分完了还是不够k
		num++;
	printf("%d",num);
	return 0;
}

201703-2 学生排队

也是一道逻辑题,一些细节注意一下即可

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
using namespace std;
const int maxn = 1010;
struct student {
	int id;
	int weizhi;
}stu[maxn];
bool cmp(student a, student b)
{
	return a.weizhi < b.weizhi;
}
int main() {
	int n,m;
	scanf("%d%d",&n,&m);
	int i,j;
	int temp1, temp2;
	int flag = 0;
	for (i = 1; i <= n; i++)
	{
		stu[i].id = i;
		stu[i].weizhi = i;
	}
	for (j = 1; j <= m; j++)
	{
		sort(stu + 1, stu + n + 1, cmp);
		/*for (i = 1; i <= n; i++)
		{
			printf("%d ", stu[i].id);
		}*/
		flag = 0;
		scanf("%d %d",&temp1,&temp2);
		if (temp2 == 0)//啥也不做
			;
		else if (temp2 < 0)//说明要向前移动
		{
			for (i = n; i >=1 && temp2 != 0; i--)
			{
				if (flag == 1)
				{
					stu[i].weizhi++;
					//printf("stu[%d].weizhi++,=%d\n", i, stu[i].weizhi);
					temp2++;
				}
				if (stu[i].id == temp1 && flag == 0)
				{
					stu[i].weizhi += temp2;
					flag = 1;
				}
			}
		}
		else//向后移动
		{
			for (i = 1; i <= n&&temp2!=0; i++)
			{				
				if (flag == 1)
				{
					//printf("!!!\n");
					stu[i].weizhi--;
					//printf("stu[%d].weizhi--,=%d\n", i, stu[i].weizhi);
					temp2--;
				}
				if (stu[i].id == temp1&&flag==0)
				{
					stu[i].weizhi += temp2;	
					flag = 1;
				}		
					
			}
		}		
	}
	sort(stu + 1, stu + n + 1, cmp);
	for (i = 1; i <= n; i++)
	{
		printf("%d ", stu[i].id);
	}	
	return 0;
}

201612-1 中间数

基础题,这题本来想用set自动去重然后排序,但是后来发现不仅中数会重复,大数和小数一样会重复,所以还是老实用数组叭,复杂度n²

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
const int maxn = 1010;
int a[maxn];
int main() {
	int n;
	scanf("%d",&n);
	int i,j;
	int left, right;
	for (i = 0; i < n; i++)
	{
		scanf("%d",&a[i]);		
	}
	sort(a, a + n);//排序
	for (i = 0; i < n; i++)
	{
		left = right = 0;
		for (j = 0; j < n; j++)
			if (a[j] < a[i])
				left++;
			else if (a[j] > a[i])
				right++;
		if (left == right)
		{
			printf("%d",a[i]);
			return 0;
		}
	}
	printf("-1");
	return 0;
}

201612-2 工资计算

这题好奇怪哟,没有四舍五入,用%g输出反而是对的,用四舍五入了输出就错了,直接cout<<输出也是对的,这样反过来做相当于做了一道数学题,,但是复杂度为0,如果正过来也可以复杂度n

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;

int main() {
	int T;
	double S;
	scanf("%d",&T);
	if (T <= 3500)
		S = T;
	else if (T <= 4955)
		S = (T - 105) * 1.0 / 0.97;
	else if (T <= 7655)
		S = (T - 455) * 1.0 / 0.9;
	else if (T <= 11255)
		S = (T - 1255) * 1.0 / 0.8;
	else if (T <= 30755)
		S = (T - 1880) * 1.0 / 0.75;
	else if (T <= 44755)
		S = (T - 3805) * 1.0 / 0.7;
	else if (T <= 61005)
		S = (T - 6730) * 1.0 / 0.65;
	else
		S = (T - 15080) * 1.0 / 0.55;
	//下面四舍五入
	//if (int(S) % 100 >= 50)
	//	S = (S / 100 + 1) * 100;
	//else
	//	S = (S / 100 ) * 100;
	printf("%g", S);
	//cout << S << endl;
	return 0;
}

201609-1 最大波动

基础题

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
const int maxn = 10000;
int a[maxn] = { 0 };
int main() {
	int n;
	scanf("%d",&n);
	int max = 0;
	int temp;
	for (int i = 0; i < n; i++)
	{
		scanf("%d",&a[i]);
	}
	for (int i = 0; i < n-1; i++)
	{
		temp = abs(a[i + 1] - a[i]);
		if (temp > max)
			max = temp;		
	}
	printf("%d",max);
	return 0;
}

201609-2 火车购票

在这里插入图片描述

逻辑题,分类讨论

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
int a[21][6];//20排,每排5个座位
int main() {
	int n;
	int i, num,j;
	int hang, lie;
	int flag;//=0表示没有找到连号的座位,反
	scanf("%d",&n);
	for (i = 1; i <=20; i++)
		for (j = 1; j <=5; j++)			
			a[i][j] = 1;//表示有座位

	for (i = 0; i < n; i++)
	{
		flag = 0;
		scanf("%d",&num);
		//下面找合适的座位;
		if (num == 1)
		{
			for (hang = 1; hang <= 20; hang++)
			{
				for (lie = 1; lie <= 5; lie++)
				{
					if (a[hang][lie] == 1)
					{
						printf("%d\n", (hang - 1) * 5 + lie);
						a[hang][lie] = 0;
						flag=1;
						break;
					}					
				}
				if (flag == 1)					
					break;
			}
			
		}
		else if (num == 2)
		{
			for (hang = 1; hang <= 20; hang++)
			{
				for (lie = 1; lie <= 5-num+1; lie++)
				{
					if (a[hang][lie] == 1 && a[hang][lie + 1] == 1)
					{
						flag = 1;
						printf("%d %d\n",(hang - 1) * 5 + lie, (hang - 1) * 5 + lie+1);
						a[hang][lie] = 0;
						a[hang][lie + 1] = 0;
						break;
					}
				}
				if (flag == 1)
					break;
			}
			if (flag == 0)//没有找到连续的座位
			{
				for (hang = 1; hang <= 20; hang++)
				{
					for (lie = 1; lie <= 5 ; lie++)
					{
						if (a[hang][lie] == 1)
						{
							printf("%d ", (hang - 1) * 5 + lie);
							a[hang][lie] = 0;
							num--;
						}
						if (num == 0)
						{
							printf("\n");
							break;
						}
							
					}
					if (num == 0)
						break;
				}
			}
		}
		else if (num == 3)
		{
			for (hang = 1; hang <= 20; hang++)
			{
				for (lie = 1; lie <= 5 - num + 1; lie++)
				{
					if (a[hang][lie] == 1 && a[hang][lie + 1] == 1&&a[hang][lie+2]==1)
					{
						flag = 1;
						printf("%d %d %d\n", (hang - 1) * 5 + lie, (hang - 1) * 5 + lie + 1, (hang - 1) * 5 + lie + 2);
						a[hang][lie] = 0;
						a[hang][lie + 1] = 0;
						a[hang][lie + 2] = 0;
						break;
					}

				}
				if (flag == 1)
					break;
			}
			if (flag == 0)//没有找到连续的座位
			{
				for (hang = 1; hang <= 20; hang++)
				{
					for (lie = 1; lie <= 5; lie++)
					{
						if (a[hang][lie] == 1)
						{
							printf("%d ", (hang - 1) * 5 + lie);
							a[hang][lie] = 0;
							num--;
						}
						if (num == 0)
						{
							printf("\n");
							break;
						}
					}
					if (num == 0)
						break;
				}
			}
		}
		else if (num == 4)
		{
		for (hang = 1; hang <= 20; hang++)
		{
			for (lie = 1; lie <= 5 - num + 1; lie++)
			{
				if (a[hang][lie] == 1 && a[hang][lie + 1] == 1 && a[hang][lie + 2] == 1&& a[hang][lie + 3] == 1)
				{
					flag = 1;
					printf("%d %d %d %d\n", (hang - 1) * 5 + lie, (hang - 1) * 5 + lie + 1, (hang - 1) * 5 + lie + 2, (hang - 1) * 5 + lie + 3);
					a[hang][lie] = 0;
					a[hang][lie + 1] = 0;
					a[hang][lie + 2] = 0;
					a[hang][lie + 3] = 0;
					break;
				}
			}
			if (flag == 1)
				break;
		}
		if (flag == 0)//没有找到连续的座位
		{
			for (hang = 1; hang <= 20; hang++)
			{
				for (lie = 1; lie <= 5; lie++)
				{
					if (a[hang][lie] == 1)
					{
						printf("%d ", (hang - 1) * 5 + lie);
						a[hang][lie] = 0;
						num--;
					}
					if (num == 0)
					{
						printf("\n");
						break;
					}
				}
				if (num == 0)
					break;
			}
		}
		}
		else
		{
		for (hang = 1; hang <= 20; hang++)
		{
			
				if (a[hang][1] == 1 && a[hang][2] == 1 && a[hang][3] == 1&&a[hang][4]==1&&a[hang][5]==1)
				{
					flag = 1;
					printf("%d %d %d %d %d\n", (hang - 1) * 5 + 1, (hang - 1) * 5 + 2, (hang - 1) * 5 +3, (hang - 1) * 5 + 4, (hang - 1) * 5 + 5);
					a[hang][1] = 0;
					a[hang][2] = 0;
					a[hang][3] = 0;
					a[hang][4] = 0;
					a[hang][5] = 0;
					break;
				}			
		}
		if (flag == 0)//没有找到连续的座位
		{
			for (hang = 1; hang <= 20; hang++)
			{
				for (lie = 1; lie <= 5; lie++)
				{
					if (a[hang][lie] == 1)
					{
						printf("%d ", (hang - 1) * 5 + lie);
						a[hang][lie] = 0;
						num--;
					}
					if (num == 0)
					{
						printf("\n");
						break;
					}
				}
				if (num == 0)
					break;
			}
		}
		}
	}
	return 0;
}

201604-1折点计数

基础题

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
const int maxn = 1010;
int a[maxn] = { 0 };
int main() {
	int n;
	int i;
	int num = 0;
	scanf("%d",&n);
	for (i = 0; i < n; i++)
	{
		scanf("%d",&a[i]);
	}
	for (i = 1; i < n - 1; i++)
	{
		if( (a[i]<a[i - 1] && a[i]<a[i + 1] )||( a[i]>a[i - 1] && a[i]>a[i + 1]))
			num++;
	}
	printf("%d",num);
	return 0;
}

201604-2 俄罗斯方块

在这里插入图片描述

这一题注意不能只对比最后一行有效行,需要对比b中的所有行才可以,同时最后一行有冲突,和没有行有冲突,这两种情况是不一样的。
下面几个容易出错的测试样例;
样例1:

0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 0 1 0 1 1 1 1
0 0 0 0 1 0 0 0 0 0
0 0 0 0
0 0 0 0
0 1 1 1
0 0 0 1
3

样例2:

0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0
1 1 1 0 1 0 1 1 1 1
0 0 0 0 1 0 0 0 0 0
1 0 0 0
1 0 0 0
1 0 0 0
1 0 0 0
3

AC代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;

int a[16][11];
int b[5][5];
int main() {
	int n;
	int i,j;
	int k;
	//输入变量
	for(i=1;i<=15;i++)
		for (j = 1; j <=10; j++)
		{
			scanf("%d",&a[i][j]);
		}
	for (i = 1; i <= 4; i++)
		for (j = 1; j <= 4; j++)
		{
			scanf("%d",&b[i][j]);
		}
	scanf("%d",&n);//第n列
	//下面找有冲突的行和列
	int ctRow=0;//数组a中的冲突行
	int ctRow1;//数组b中的冲突行
	int row;//数组b有效的行数
	int hang = 1;//循环变量
	
	//记录下b[][]中不为1的最下面一行row
	for (i = 4; i >= 1; i--)//从下向上遍历
	{		
			if (b[i][1] != 0||b[i][2]!=0||b[i][3]!=0||b[i][4]!=0)
			{
				row = i;
				break;
			}
	}
	//不断向下直到走不动!注意这里容易出错,不能只看最后一行有没有冲突,要遍历1-row行,j即是有冲突的行
	for (i = 1; i+row-1 <=15; i++)
	{
		hang = 1;
		for (j = i; j <= i + row-1; j++)
		{
			//printf("现在对比到数组a第%d行,数组b第%d行\n",j,hang);
			if (a[j][n] + b[hang][1] == 2 || a[j][n + 1] + b[hang][2] == 2 || a[j][n + 2] + b[hang][3] == 2 || a[j][n + 3] + b[hang][4] == 2)
			{
				//printf("!!!\n");
				ctRow = j;
				ctRow1 = hang;
				break;				
			}
			hang++;
		}
		if (ctRow !=0)
			break;			
	}

	if (ctRow == 0)//如果一直没有冲突
	{
		j = 15-row+1;
		for (hang=1; hang <= row;hang++ )//一共ctRow行
		{
			a[j][n] += b[hang][1]; a[j][n + 1] += b[hang][2]; a[j][n + 2] += b[hang][3]; a[j][n + 3] += b[hang][4];			
			j++;
		}
	}
	else//如果有冲突的行
	{
		hang = 1;
		j = ctRow -ctRow1;
		for (; hang <= row; )//一共ctRow行
		{
			a[j][n] += b[hang][1]; a[j][n + 1] += b[hang][2]; a[j][n + 2] += b[hang][3]; a[j][n + 3] += b[hang][4];
			hang++;
			j++;
		}
	}

	//输出结果
	for (i = 1; i <= 15; i++)
	{
		for (j = 1; j <= 10; j++)
		{
			printf("%d ", a[i][j]);
		}
		printf("\n");
	}		
	return 0;
}

201512-1 数位之和

好基础

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
int main() {
	int a;
	int sum=0;
	scanf("%d",&a);
	while (a != 0)
	{
		sum += a % 10;
		a /= 10;
	}
	printf("%d",sum);
	return 0;
}

201512-2 消除类游戏

hashtable存储即可

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
int a[30][30];
int hashtable[30][30];
int main() {
	int m, n;
	int i, j;
	scanf("%d %d",&n,&m);
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < m; j++)
		{
			scanf("%d",&a[i][j]);
			hashtable[i][j] = 0;
		}
	}
	//先遍历每一行
	for (i = 0; i < n; i++)
	{
		for (j = 0; j <= m - 3; j++)
		{
			if (a[i][j] == a[i][j + 1] && a[i][j + 1] == a[i][j + 2])
			{
				hashtable[i][j] = 1;
				hashtable[i][j + 1] = 1;
				hashtable[i][j + 2] = 1;
			}
		}
	}
	for (j = 0; j < m; j++)
	{
		for (i = 0; i <= n - 3; i++)
		{
			if (a[i][j] == a[i+1][j] && a[i+1][j] == a[i+2][j])
			{
				hashtable[i][j] = 1;
				hashtable[i+1][j] = 1;
				hashtable[i+2][j] = 1;
			}
		}
	}
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < m; j++)
		{
			if (hashtable[i][j] == 1)
				printf("0 ");
			else
				printf("%d ",a[i][j]);
		}
		printf("\n");
	}
	return 0;
}

201509-1 数列分段

基础题

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
int main() {
	int n, num, i;
	int duibi;
	int duan;
	scanf("%d",&n);
	scanf("%d",&num);
	duibi = num;
	duan = 1;
	for (i = 1; i < n; i++)
	{
		scanf("%d", &num);
		if (num != duibi)
		{		
			duan++;
			duibi = num;
		}
	}
	printf("%d",duan);
	return 0;
}

201509-2日期处理

基础的日期处理,设置一个二位数组存放各个月份的日期即可

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
int mouths[2][13] = { {0,31,28,31,30,31,30,31,31,30,31,30,31},{0,31,29,31,30,31,30,31,31,30,31,30,31} };
int main() {
	int year, days;
	int mouth=0, day;
	scanf("%d %d",&year,&days);
	int flag;
	if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
		flag = 1;
	else
		flag = 0;
	while (days > 0)
	{
		if (days <= mouths[flag][mouth + 1])
			break;
		else
		{
			days -= mouths[flag][mouth + 1];
			mouth++;
		}	}
	printf("%d\n%d",mouth+1,days);
	return 0;
}

201503-1图像旋转

限时5s,还好些,看到运行1s多震惊了

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
int a[1000][1000];
int main() {
	int m, n;
	scanf("%d %d",&n,&m);
	int i, j;
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < m; j++)
		{
			scanf("%d",&a[i][j]);
		}
	}
	for (j = m-1; j >=0; j--)
	{
		for (i = 0; i <n; i++)
		{
			printf("%d ",a[i][j]);
		}
		printf("\n");
	}
	return 0;
}

201503-2 数字排序

基础题

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
const int maxn = 1010;
struct Num
{
	int num;
	int count;
}a[maxn];
bool cmp(Num a, Num b)
{
	if (a.count != b.count) return a.count > b.count;
	else return a.num < b.num;
}
int main() {
	int n;
	int i;
	int num;
	scanf("%d",&n);
	for (i = 0; i < maxn; i++)
	{
		a[i].num = i;
		a[i].count = 0;
	}
	for (i = 0; i < n; i++)
	{
		scanf("%d",&num);
		a[num].count++;
	}
	sort(a, a + maxn,cmp);
	i = 0;
	while (a[i].count != 0)
	{
		printf("%d %d\n", a[i].num, a[i].count);
		i++;
	}	
	return 0;
}

201412-1门禁系统

基础题

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
const int maxn = 1010;
int a[1010] = {0};//记录最多1000位读者出现的次数
int main() {
	int n, i;
	int id;
	scanf("%d",&n);
	for (i = 0; i < n; i++)
	{
		scanf("%d",&id);
		a[id]++;
		printf("%d ",a[id]);
	}	
	return 0;
}

201412-2 Z字形扫描

在这里插入图片描述

这题有两个要点:首先是在循环内的判断需要保证先判断是否等于n,再判断是否等于1;其次是在输出的时候一定要有逻辑,知道离开循环的时候循环变量的值都是多少,会不会输出下标范围以外的,或者下一次循环期望值以外的i或者j
要注意样例给的是n=4,代码里我一开始直接用j<4来判断了,这样肯定不对,如果只得10分可能是这个原因orz

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
const int maxn = 510;
int a[510][510];
int main() {
	int n, i,j;
	scanf("%d",&n);
	for (i = 1; i <= n; i++)
	{
		for (j = 1; j <= n; j++)
		{
			scanf("%d", &a[i][j]);
		}
	}
	i = j = 1;
	while (i + j <= 2 * n)
	{
		if (j == n) //左下
		{
			printf("%d ", a[i][j]);	
			i++;			
			while (i < n)
			{			
				printf("%d ", a[i][j]);	
				i++;
				j--;
			}
			continue;
		}
		if (i == n) //右上
		{		
			printf("%d ", a[i][j]);	
			j++;			
			while (j < n)
			{				
				printf("%d ", a[i][j]);	
				j++;
				i--;
			}
			continue;
		}
		if (i == 1) //左下
		{			
			printf("%d ", a[i][j]);			
			j++;
			while (j > 1)
			{				
				printf("%d ", a[i][j]);
				i++;
				j--;
			}
			continue;
		}
		if (j == 1)//右上
		{
			printf("%d ", a[i][j]);
			i++;
			while (i > 1)
			{
				printf("%d ", a[i][j]);
				i--;
				j++;
			}
			continue;
		}			
	}	
	return 0;
}

201409-1 相邻数对

基础题

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
const int maxn = 1010;
int a[maxn];
int main() {
	int n, i;
	int num = 0;
	scanf("%d",&n);
	for (i = 0; i < n; i++)
	{		
		 scanf("%d", &a[i]);		
	}
	sort(a,a + n);
	for (i = 0; i < n-1; i++)
	{
		if (a[i] == a[i + 1] - 1)
			num++;
	}
	printf("%d",num);
	return 0;
}

201409-2画图

把对图中每一块的填色设为对左下角点的标价,用hashtable[10000],来存储二维的100*100个坐标

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
const int maxn = 10010;
int hashtable[maxn] = {0};
int main() {
	int n, i,j,k;
	int num = 0;
	int x1, y1, x2, y2;
	scanf("%d",&n);
	for (i = 0; i < n; i++)
	{		
		scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
		x2--; y2--;
		for(j=x1;j<=x2;j++)
			for (k = y1; k <= y2; k++)
			{
				hashtable[j * 100 + k] = 1;
			}
	}
	for (i = 0; i < maxn; i++)
	{
		num += hashtable[i];
	}	
	printf("%d",num);
	return 0;
}

201403-1相反数

基础题,这几年一直在考察hash啊

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
const int maxn = 1010;
int hashtable[maxn] = {0};
int main() {
	int n, i;
	int num ;	
	scanf("%d",&n);
	for (i = 0; i < n; i++)
	{		
		scanf("%d", &num);
		hashtable[abs(num)]++;
	}
	num = 0;//表示一共有多少对
	for (i = 0; i < maxn; i++)
	{
		if (hashtable[i] == 2)
			num++;
	}	
	printf("%d",num);
	return 0;
}

201403-2 窗口

结构体排序

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
struct Window
{
	int cengci;//cengci=n说明在最上面
	int id;//id表示编号
	int x1;
	int x2;
	int y1;
	int y2;
}win[12];//最多10个窗口
bool cmp(Window a, Window b)
{
	return a.cengci < b.cengci;
}
int main() {
	int n, m;
	int i;
	int tempx, tempy;
	int j;
	scanf("%d %d", &n, &m);
	for (i = 1; i <=n; i++)
	{
		scanf("%d %d %d %d", &win[i].x1, &win[i].y1, &win[i].x2, &win[i].y2);
		win[i].id = i;
		win[i].cengci = i;//
	}
	int tempcengci;
	int tempid;
	for (i = 1; i <= m; i++)
	{
		tempcengci = 0;
		sort(win+1, win +1+ n, cmp);//注意sort是怎么写的		
		scanf("%d %d",&tempx,&tempy);
		for (j = n; j >=1; j--)//从cengci由大到小,即从最上面开始选
		{
			if (win[j].x1 <= tempx && win[j].y1 <= tempy && win[j].x2 >= tempx && win[j].y2 >= tempy)
			{
				printf("%d\n",win[j].id);//如果选到了,就把之前的id输出
				tempcengci = win[j].cengci;
				tempid = win[j].id;
				win[j].cengci = n;//排在最前面
				break;
			}
		}
		if (tempcengci == 0)
		{
			printf("IGNORED\n");
		}
		else
		{
			for (j = n; j >= 1; j--)//从cengci由大到小,即从最上面开始选
			{
				if(win[j].cengci > tempcengci&&win[j].id!=tempid)
					win[j].cengci--;
			}
		}
	}
	return 0;
}

201312-1 出现次数最多的数

hash表

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
const int maxn = 10010;
int hashtable[maxn] = { 0 };
int main() {
	int n;
	int i;
	int num;
	scanf("%d", &n);
	for (i = 0; i < n; i++)
	{
		scanf("%d",&num);
		hashtable[num]++;
	}
	int max = 0;
	for (i = 0; i < maxn; i++)
	{
		if (hashtable[i] > hashtable[max])
			max = i;
	}
	printf("%d",max);
	return 0;
}

201312-2 ISBN号码

记得数组要取大一点,因为要包括后面的结束符\0

#define _CRT_SECURE_NO_WARNINGS 1
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
int main() {
	char a[15];
	scanf("%s",a);
	int num=0;//计算正确的识别码
	int temp = 1;
	for (int i = 0; i <= 10; i++)
	{
		if (i != 1 && i != 5)
		{
			num += (a[i] - '0') * temp;
			temp++;
		}
	}
	num %= 11;
	if (num != 10)
	{
		if (num == a[12] - '0')
		{
			printf("Right");
		}
		else
		{
			a[12] = num + '0';
			printf("%s", a);
		}
	}
	else
	{
		if (a[12] == 'X')
		{
			printf("Right");
		}
		else
		{
			a[12] ='X';
			printf("%s", a);
		}
	}
	
	return 0;
}

撒花花★,°:.☆( ̄▽ ̄)/$:.°★

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值