CSP往年题解记录

小中大

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,i;
	int a[100000];
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	sort(a+1,a+n+1);

	if(n%2){
		printf("%d %d %d",a[n],a[(n+1)/2],a[1]);
	}
	else{
		if((a[n/2]+a[n/2+1])%2) 
			printf("%d %.1f %d",a[n],float(a[n/2]+a[n/2+1])/2,a[1]);
		else
			printf("%d %d %d",a[n],(a[n/2]+a[n/2+1])/2,a[1]);
	}
	return 0;
}

.1f直接四舍五入
sort排序范围

二十四点

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
stack<int> a;
stack<char> c;
int main() {
	int n,res,f1,f2,j;
	char s[8];
	scanf("%d",&n);
	for(int i=0; i<n; i++) {
		res=0;
		scanf("%s",s);
		for(int j=0; j<7; j++) {
			if(s[j]>='1'&&s[j]<='9') {
				a.push(s[j]-'0');
			} else {
				if(s[j]=='+'||s[j]=='-') {
					c.push(s[j]);
				} else {
					if(s[j]=='x') {
						a.push(s[++j]-'0');
						f1=a.top();
						a.pop();
						f2=a.top();
						a.pop();
						res+=f2*f1;
					} else {
						a.push(s[++j]-'0');
						f1=a.top();
						a.pop();
						f2=a.top();
						a.pop();
						res+=f2/f1;
					}

					a.push(res);
				}
			}
		}
		while(!a.empty()) {
			f1=a.top();
			a.pop();
			if(!a.empty()) f2=a.top();
			a.pop();
			if(!c.empty()) {
				if(s[j]=='+') res+=f2+f1;
				else res+=f2-f1;
				a.push(res);
			}
		}
		if(a.empty()) {
			if(f1==24) printf("Yes\n");
			else printf("No\n");
		}
	}
	return 0;
}

AC:

#include<bits/stdc++.h>
using namespace std;
int n;
char str[10];
stack<int> num;
stack<char> sign;//ke sheng
int main(){
	scanf("%d",&n);
	getchar();
	for(int i=0;i<n;i++){
		gets(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;
}

回收站选址

10分:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,i,f[1000][1000]={0},x[1000],y[1000],tmp,a[5]={0};
	scanf("%d",&n);
	for(i=0;i<n;i++){
		scanf("%d%d",&x[i],&y[i]);
		f[x[i]][y[i]]=1;
	}
	for(i=0;i<n;i++){
		if(f[x[i]-1][y[i]]&&f[x[i]+1][y[i]]&&f[x[i]][y[i]-1]&&f[x[i]][y[i]+1]){
			tmp+=f[x[i]-1][y[i]-1]+f[x[i]-1][y[i]+1]+f[x[i]+1][y[i]-1]+f[x[i]+1][y[i]+1];
			a[tmp-1]++;
		}
	}
	for(i=0;i<5;i++){
		printf("%d\n",a[i]);
	}
	return 0;
	
}

tmp累加,没有归0,导致超出A的范围
坐标值范围比较大,而且坐标有可能是负数,难以用矩阵来存储坐标点,所以使用稀疏矩阵来存储。用STL的map来存储坐标是最为简单的。用C语言实现的话,要复杂很多,所以就不做题解了。

/* CCF201912-2 回收站选址 */

#include <bits/stdc++.h>

using namespace std;

const int N = 1000;
pair<int, int> p[N];
const int CN = 4;
int cnt[CN + 1];

int main()
{
    int n;
    map<pair<int, int>, int> ps;

    scanf("%d", &n);
    for(int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);

        p[i] = make_pair(x, y);
        ps[p[i]] = 1;
    }

    memset(cnt, 0, sizeof(cnt));
    for(int i = 0; i < n; i++) {
        int x = p[i].first;
        int y = p[i].second;

        if(ps[make_pair(x, y -1)] && ps[make_pair(x, y + 1)] &&
                ps[make_pair(x - 1, y)] && ps[make_pair(x + 1, y)])
            cnt[ps[make_pair(x - 1, y - 1)] + ps[make_pair(x - 1, y + 1)] +
                    ps[make_pair(x + 1, y - 1)] + ps[make_pair(x + 1, y + 1)]]++;
    }

    for(int i = 0; i <= CN; i++)
        printf("%d\n", cnt[i]);

    return 0;
}

买菜

10分:

#include<bits/stdc++.h>
using namespace std;
int main(){
	
	int n,ssum=0,a[2001][2],b[2001][2];
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&a[i][0],&a[i][1]);
	}
	for(int i=1;i<=n;i++){
		scanf("%d%d",&b[i][0],&b[i][1]);
	}
	for(int i=1;i<=n;i++){
		if(a[i][1]>=b[i][0] && a[i][0]<=b[i][0] && b[i][1]>=a[i][1]) ssum+=a[i][1]-b[i][0];//[1,3][2,4]
		else if(a[i][1]>=b[i][0] && a[i][0]<=b[i][0] && b[i][1]<=a[i][1]) ssum+=b[i][1]-b[i][0];
		else if(b[i][1]>=a[i][0] && b[i][0]<=a[i][0] && a[i][1]<=b[i][1]) ssum+=a[i][1]-a[i][0];
		else if(a[i][1]<=b[i][0]) ssum+=0;
		else if(b[i][1]<=a[i][0]) ssum+=0;
		else if(a[i][0]>=b[i][0] && a[i][0]<=b[i][1]&& b[i][1]<=a[i][1]) ssum+=b[i][1]-a[i][0];
		else if(a[i][1]>=b[i][1] && a[i][0]<=b[i][0]) ssum+=b[i][1]-b[i][0];
		else if(b[i][1]>=a[i][1] && b[i][0]<=a[i][0]) ssum+=a[i][1]-a[i][0];
		//else if(b[i][1]>a[i][0] && b[i][0]<=a[i][0]) ssum+=b[i][1]-a[i][0];// [2,4][1,3]
	}
	printf("%d",ssum);
	
	return 0;
} 

100分:
感觉10分那个思路就是不行的,这个:转换为一维数组的重合部分,注意两个端点只能算一个

for(j=t1+1;j<=t2;j++){
	A[j]+=1;
}
#include<bits/stdc++.h>
using namespace std;
int A[1000001]={0};
int main(){
	int n,ssum=0,i,t1,t2,j;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&t1,&t2);
		for(j=t1+1;j<=t2;j++){
			A[j]=1;
		}
	}
	for(int i=1;i<=n;i++){
		scanf("%d%d",&t1,&t2);
		for(j=t1+1;j<=t2;j++){
			A[j]+=1;
		}
	}
	for(i=1;i<=1000000;i++){
		if(A[i]==2) 
		{
			ssum++;
		}
	}
	printf("%d",ssum);
	return 0;
} 

风险人群筛查

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k,t,xl,yd,xr,yu,i,j,xt,yt,res1=0,res2=0,jilu[20][1000],num,f=0;
	scanf("%d%d%d%d%d%d%d",&n,&k,&t,&xl,&yd,&xr,&yu);
	
	for(i=0;i<n;i++){
		f=0;
		for(j=0;j<t;j++){
			scanf("%d%d",&xt,&yt);
			if(xt>=xl&&xt<=xr&&yd<=yt&&yu>=yt) {
				f=1;jilu[i][j]=1;
			}
		}
		if(f) res1+=1;
	}
	for(i=0;i<n;i++){
		//判断连续kge
		num=0;f=0;
		for(j=0;j<t;j++){
			if(jilu[i][j]) num++;
			else num=0;
		//	printf("%d",num);
			if(num>=k) {
				f=1;break;
			}
		}
		//printf("%d**",f);
		if(f) res2+=1;
	}
	printf("%d\n%d",res1,res2);
	return 0;
}

稀疏向量

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,a,b,i,A[500000][2],B[500000][2],t,v,res=0;
	scanf("%d%d%d",&n,&a,&b);
	for(i=0;i<a;i++){
		scanf("%d%d",&A[i][0],&A[i][1]);
	}
	for(i=0;i<b;i++){
		scanf("%d%d",&t,&v);
		for(i=0;i<a;i++){
			if(A[i][0]==t) {
				res+=v*A[i][1];
			}
		}
	}
	printf("%d",res);
	return 0;
}

主要问题:时间复杂度高
为何必须把数组放到全局变量?

#include<bits/stdc++.h>
using namespace std;
int A[500000][2],B[500000][2];
int main(){
	int n,a,b,i,t,v,j;
	
	long long int res=0;
	scanf("%d%d%d",&n,&a,&b);
	for(i=0;i<a;i++){
		scanf("%d%d",&A[i][0],&A[i][1]);
	}
	for(i=0;i<b;i++){
		scanf("%d%d",&B[i][0],&B[i][1]);
	}
	i=0;j=0;
	while(i<b&&j<a){		
		if(A[j][0]==B[i][0]) {
			res+=A[j][1]*B[i][1];i++;j++;
		}
		else if(A[j][0]>B[i][0]) {
			i++;
		}
		else {
			j++;
		}
	}
	printf("%lld",res);
	return 0;
}

邻域均值

边界没处理好,浮点数:

#include<bits/stdc++.h>
using namespace std;
int A[600][600];
int main(){
	int n,L,r,t,j,ssum=0,num=0,tmp,res=0,i,xt,yt;
	scanf("%d%d%d%d",&n,&L,&r,&t);
	for(i=0;i<n;i++){
		for(j=0;j<n;j++)
		scanf("%d",&A[i][j]);
	}
	for(i=0;i<n;i++){
		for(j=0;j<n;j++)
		{
			num=0;ssum=0;
			xt=i-r;
			if(xt<0) xt=0;
			while(xt<=r+i){//行 
				yt=j-r;
				if(yt<0) yt=0;
				while(yt<=r+j)
				{	ssum+=A[xt][yt];num++;
					
					yt++;	
				}
				xt++;
			}
			tmp=ssum/num;
			if(tmp<=t) res++;
		}
	}
	printf("%d",res-2);
	return 0;
}
#include<bits/stdc++.h>
using namespace std;
int A[600][600];
int main(){
	int n,L,r,t,j,res=0,i,xt,yt;
	float tmp=0.0,ssum=0.0,num=0.0;
	scanf("%d%d%d%d",&n,&L,&r,&t);
	for(i=0;i<n;i++){
		for(j=0;j<n;j++)
		scanf("%d",&A[i][j]);
	}
	for(i=0;i<n;i++){
		for(j=0;j<n;j++)
		{
			num=0;ssum=0;
			xt=i-r;
			if(xt<0) xt=0;
			while(xt<=r+i&&xt<n){//行 
				yt=j-r;
				if(yt<0) yt=0;
				while(yt<=r+j&&yt<n)
				{	ssum+=A[xt][yt];num++;
					//printf("%d %d %f  %f %d %d\n",xt,yt,ssum,num,i,j); 
					yt++;	
				}
				xt++;
			}
			tmp=ssum/num;//printf("%f %d %d\n",tmp,i,j); 
			if(tmp<=t) res++;
		}
	}
	printf("%d",res);
	return 0;
}

原来改进一点就可以满分啊
在这里插入图片描述
先计算出每一行的第一个元素

#include<stdio.h>
int main(){
    int i,j,n,L,r,t,t1,t2,end=0;
    int a,b,c,d;//对于中心元素,邻域左上元素为s[a][b],右下元素为s[c][d]
    int a1,b1,c1,d1;//对于新的中心元素,邻域左上元素为s[a1][b1],右下元素为s[c1][d1]
    float sum,num;//sum为目前元素总值,num为目前元素总个数
    scanf("%d%d%d%d",&n,&L,&r,&t);
    int s[n][n];
    for(i=0;i<n;i++) for(j=0;j<n;j++) scanf("%d",&s[i][j]);
    for(i=0;i<n;i++){
        j=0;sum=0;num=0;//每一行对第一个元素计算,重新赋初值
        //确定邻域范围a,b,c,d
        a=i-r;if(a<0) a=0;
        b=j-r;if(b<0) b=0;
        c=i+r;if(c>=n) c=n-1;
        d=j+r;if(d>=n) d=n-1;
        //计算第一个元素的邻域
        for(t1=a;t1<c+1;t1++){
            for(t2=b;t2<d+1;t2++){
                sum+=s[t1][t2];
                num++;
            }
        }
        if(sum/num<=t) end++;
        //计算本行之后元素的邻域
        for(j=1;j<n;j++){
            //确定新的邻域范围a1,b1,c1,d1
            a1=i-r;if(a1<0) a1=0;
            b1=j-r;if(b1<0) b1=0;
            c1=i+r;if(c1>=n) c1=n-1;
            d1=j+r;if(d1>=n) d1=n-1;
            //判断左边界是否变化,若变化则减去
            if(b1!=b){
                for(t1=a;t1<c+1;t1++){
                    sum-=s[t1][b];
                    num--;
                }
            }
            //判断右边界是否变化,若变化则加上
            if(d1!=d){
                for(t1=c;t1>=a;t1--){
                    sum+=s[t1][d1];
                    num++;
                }
            }
            if(sum/num<=t) end++;
            a=a1;b=b1;c=c1;d=d1;//重新定义目前邻域范围
        }
    }
    printf("%d",end);
    return 0;
}

跳一跳

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,res=0,f;
	scanf("%d",&n);
	if(n==1) res+=1;
	else if(n==2) res+=2;
	printf("%d\n",res);
	while(n){
		scanf("%d",&n);
		if(n==1) { 
		res+=1;f=0;printf("%d\n",res);
	}
	else if(n==2) {
		f+=1;res+=f*2;printf("%d\n",res);
	}
}
	printf("%d",res);
	return 0;
}

60分

游戏

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k,A[1000]={0},num,shu=0,i;
	scanf("%d%d",&n,&k);
	num=n;
	while(num>1){
		for(i=0;i<n;i++){
			if(A[i]==0)
				{
					shu++;
					if((shu%k==0)||(shu%10==k)){
						A[i]=1;//淘汰 
						num--; 
				    }
		        }
	    }
	}
	for(i=0;i<n;i++){
		if(A[i]==0) printf("%d",i+1);
	}
	
	return 0;
}

90分
AC: 当k=1时,第一次就把所有的元素淘汰完了

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k,A[1000]={0},num,shu=0,i;
	scanf("%d%d",&n,&k);
	if(k==1){
		printf("%d",n);return 0;
	}  
	num=n;
	while(num>1){
		for(i=0;i<n;i++){
			if(A[i]==0)
				{
					shu++;//printf("%d",shu);
					if((shu%k==0)||(shu%10==k)){
						A[i]=1;//淘汰 
						num--; 
				    }
		        }
	    }
	}
	for(i=0;i<n;i++){
		if(A[i]==0) printf("%d",i+1);
	}
	
	return 0;
}

也对的code

while(num>1){
		for(i=0;i<n;i++){
			if(A[i]==0&&num>1)
				{
					shu++;//printf("%d",shu);
					if((shu%k==0)||(shu%10==k)){
						A[i]=1;//淘汰 
						num--; 
				    }
		        }
	    }
	}

学生排队

#include<bits/stdc++.h>
using namespace std;
int main() {
	int n,k,i,A[1000]= {0},t1,t2,j,t,tmp;
	scanf("%d%d",&n,&k);
	for(i=1; i<=n; i++) {
		A[i]=i;
	}
	for(i=1; i<=k; i++) {
		scanf("%d%d",&t1,&t2);
		for(t=1; t<=n; t++) {
			if(A[t]==t1) t1=t;
		}
		tmp=A[t1];//3
		if(t2>0) {
			for(j=t1+1; j<=t1+t2; j++) {
				A[j-1]=A[j];
			}
			A[t1+t2]=tmp;
			for(t=1; t<=n; t++) {
				printf("%d ",A[t]);
			}
			printf("\n");
		}
		else if(t2<0) {
			t2=-t2;
			for(j=t1; j>t1-t2; j--) {
				A[j]=A[j-1];
			}
			A[t1-t2]=tmp;
			for(t=1; t<=n; t++) {
				printf("%d ",A[t]);
			}
			printf("\n");
		}
	}
	for(i=1; i<=n; i++) {
		printf("%d ",A[i]);
	}


	return 0;
}

中间数

30:

#include<bits/stdc++.h>
using namespace std;
int main() {
	int n,k,i,A[1000]= {0},d=0,x=0,j;
	scanf("%d",&n);
	if(n==1) {
		printf("%d",n);return 0;
	}
	for(i=1; i<=n; i++) {
		scanf("%d",&A[i]);
	}
	for(i=1; i<=n; i++) {
		d=0;x=0;
		for(j=1;j!=i&&j<=n;j++){
			if(A[j]>A[i]) d++;
			else if(A[j]<A[i]) x++;
		}
		if(d&&(d==x)){
			printf("%d",A[i]);return 0;
		}
	}
	printf("-1");
	
	
}

消除类游戏

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,m,A[30][30],B[30][30],i,j,f,max,t,maxi;
	scanf("%d%d",&n,&m);
	for(i=0;i<n;i++){
		for(j=0;j<m;j++)
			{
				scanf("%d",&A[i][j]);B[i][j]=A[i][j];
			}
	}
	for(i=0;i<n;i++){
		t=1;f=0;
		for(j=0;j<m-1;j++){
			if(A[i][j]==A[i][j+1]){
				t++;
			}
			if(t>=3) {
				f=1;max=t;maxi=j+1;
			}
			if(A[i][j+1]!=A[i][j]) t=0;
		}
		if(f=1){
			for(j=maxi;j>=maxi-max+1;j--){
				A[i][j]=0;
			}
		}
	}
	for(i=0;i<m;i++){
		t=1;f=0;
		for(j=0;j<n-1;j++){
			if(B[j][i]==B[j+1][i]){
				t++;
			}
			if(t>=3) {
				f=1;max=t;maxi=j+1;
			}
			if(B[j][i]!=B[j+1][i]) t=0;
		}
		if(f=1){
			for(j=maxi;j>=maxi-max+1;j--){
				B[j][i]=0;
			}
		}
	}
	for(i=0;i<n;i++){
		for(j=0;j<m;j++){
			if(A[i][j]&&B[i][j]){
				printf("%d ",A[i][j]);
			}
			else printf("0 ");
		}
		printf("\n");
	}
	
	return 0;
} 

数列分段

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,i,A[1001]={0},t=1;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d",&A[i]);
	}
	for(i=1;i<n;i++){
		if(A[i+1]-A[i]) t++;
	}
	printf("%d",t);
	return 0;
}

公共钥匙盒

30分:

#include<bits/stdc++.h>
using namespace std;
struct tea {
	int index;
	int b;
	int e;
} T[1000],T1[1000];
bool cmp(tea a,tea a1) {
	return a.b<a1.b;
}
bool cmp1(tea a,tea a1) {
	return a.e<a1.e;
}
int main() {
	int n,k,i,A[1000],j,t,num=0,ji,f=0;
	scanf("%d%d",&n,&k);
	for(i=1; i<=n; i++) {
		A[i]=i;
	}
	for(i=0; i<k; i++) {
		scanf("%d%d%d",&T[i].index,&T[i].b,&T[i].e);
		T[i].e=T[i].e+T[i].b;
		T1[i]=T[i];
	}
	sort(T,T+k,cmp);
	j=0;
	sort(T1,T1+k,cmp1);
	/*for(i=0; i<k; i++) {
		printf("%d ",T1[i].index);
	}*/
	for(i=0; i<k||j<k;) {
		if(i>=k) f=1;
		if(T[i].b<T1[j].e&&(!f)) {
			for(t=1;t<=n;t++){
				if(A[t]==T[i].index) 	{
					A[t]=0;i++;break;
				}
			}
		} else {
		//	printf("%d*88***",j);

			num=0;
			for(t=1; t<=n; t++) {
				if(A[t]==0) {
					num++;
				}
				if(num==1) {
					ji=t;break;
				}
			}
			/*	if(num==1) A[T1[j].index]=T1[j].index;
				else {
					A[ji]=T1[j].index;
				}*/
			A[ji]=T1[j].index;	j++;//printf("%d\n",T1[j].index);
	
		}

	}
	for(i=1; i<=n; i++) {
		printf("%d ",A[i]);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值