CCF-CSP认证202403个人总结以及部分代码

第一次参加,总分340,这个成绩个人觉得比较满意了,毕竟考前一直在划水,也很久没写算法题了。写到第四题,觉得还剩一个小时肯定写不完就又开始划水,暴力模拟完了就开始翻网页抄自己的提交记录,无所事事,想提前交卷。考试结束在网上一搜,第四题好像不是很难,瞬间觉得没写到最后亏了,开始后悔。

考前做了CSP题库最近三次的前两题熟悉题型,但是个人感觉对我自己来说做多了好像也没有很大用处,除非考试做到后两题,没想到真给我做到了(?)。

很久没碰过C++了,STL可以说是非常陌生,迭代器翻书找半天,set交集并集考试的时候翻书才知道直接有现成的可以用(拿的C++PrimerPlus第六版,不愧是这么厚一本,还是有用的)。前三题都是一遍过,出乎意料,意外的顺利,就是可惜第三题时间耗得有点长。

记录一下提交(无所事事的时候对着电脑抄下来的):

提交序号 提交时间 题号 得分
109 13:40:45 1 100
1307 14:24:15 2 100
4693 16:32:54 3 100
5729 17:02:29 4 0(辅助输出没删)
5864 17:06:22 4 30(看数据大小感觉还能多混点)
6230 17:15:45 4 40
6264 17:16:20 4 40(觉得肯定写不完了,开始无所事事)

以下是部分根据本人记忆复现的代码,本人代码可能十分混乱,不是写的清楚明白的那一类,已经尽力修改过了,仅供参考。


202403-1


签到题。

#include<iostream>
using namespace std;
typedef long long ll;
const int MAX=1e2+5;
int n,m,article[MAX]={0},count[MAX]={0};

int main(){
	cin>>n>>m;//文章数 词种类数 
	for(int i=1;i<=n;i++){
		bool flag[MAX]={false};//一定要初始化 
		int l,z;
		cin>>l;//该文章的词数 
		for(int j=1;j<=l;j++){
			cin>>z;//第几个词 
			count[z]++;
			if(!flag[z]){
				flag[z]=true;//本文章中该词已被计算过 
				article[z]++;
			}
		}
	}
	for(int i=1;i<=m;i++){
		cout<<article[i]<<" "<<count[i]<<endl;
	}
	return 0;
}

202403-2


并集直接使用的STL的函数,其实交集也有,只不过我当时已经写完了才看到书上有,因为已经AC了就没改。

#include<iostream>
#include<string>
#include<set>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAX=1e4+5;
int n,m;
set<string> se1,se2;

string change(string s){//全转换成小写
	for(int i=0;i<s.length();i++){
		if(s[i]>='A'&&s[i]<='Z'){
			s[i]=s[i]-'A'+'a';
		}
	}
	return s;
}

int main(){
	cin>>n>>m;
	string str;
	for(int i=1;i<=n;i++){
		cin>>str;
		str=change(str);
		se1.insert(str);
	}
	for(int i=1;i<=m;i++){
		cin>>str;
		str=change(str);
		se2.insert(str);
	}
	//交集
	set<string> se_j;
	set<string>::iterator it1=se1.begin();
	for(;it1!=se1.end;it1++){
		set<string>::iterator it2=se2.begin();
		for(;it2!=se2.end();it2++){
			if(*it1==*it2){
				se_j.insert(*it);
			}
		}
	} 
	cout<<se_j.size()<<endl;
	//并集
	set<string> se_u;
	set_union(se1.begin(),se1.end(),se2.begin(),se2.end(),insert_iterator<set<string> >(se_u,se_u.begin()));
	cout<<se_u.size()<<endl;
	return 0;
}


202403-3


大模拟,我没有高斯消元的板子,之前也没写过高斯消元的题,只能跟着提示写。

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAX=40+5;
int n,m;
double ans[MAX][MAX]={{0}};
vector<string> ve;//记录该元素是第几行 

void gs(double a[MAX][MAX],int x,int xe,int y,int ye){
	if(x>=xe||y>=ye){
		for(int i=0;i<ve.size();i++){
			for(int j=0;j<m;j++){
				ans[i][j]=a[i][j];
			}
		}
		return;
	}
	bool flag=false;
	for(int i=x;i<xe;i++){//考察矩阵第一列上的元素 
		if(a[i][y]){
			flag=true;//不全为0 
			break;
		}
	}
	if(!flag){
		gs(a,x,xe,y+1,ye);//全为0,对除去该列的子矩阵重复上述判断 
		return;
	}
	if(!a[x][y]){//交换行,让第一行第一个元素非零 
		int index=x+1;
		bool flag2=false;
		while(index<xe){
			if(a[index][y]!=0){
				flag2=true;
			}
		}
		if(flag2){//找到非0行 
			for(int i=y;i<ye;i++){//交换该行 
				double tmp=a[index][i];
				a[index][i]=a[x][i];
				a[x][i]=tmp;
			}
			double div=a[x][y];
			for(int j=y+1;j<ye;j++){//该行第一列元素化为1,便于计算 
				a[x][j]/=div;
			}
		}
	}
	for(int i=x+1;i<xe;i++){//遍历每行 
		double mul=(a[i][y]/a[x][y])*(-1);//减的倍数
		for(int j=y;j<ye;j++){
			a[i][j]+=a[x][j]*mul;
		} 
	}
	gs(a,x+1,xe,y+1,ye);
	return;
}

int count(double a[MAX][MAX],int x,int xe,int y,int ye){
	int cnt=0;
	for(int i=x;i<xe;i++){
		bool flag3=false;
		for(int j=y;j<ye;j++){
			if(a[i][j])flag3=true;//非0 
		}
		cnt+=flag3;
	}
	return cnt;
}

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		ve.erase(ve.begin(),ve.end());
		double ys[MAX][MAX]={{0}};
		cin>>m;
		string str;
		for(int j=0;i<m;j++){//列 元素是行 
			cin>>str;
			int boundary=0;//左边界 
			for(int k=0;k<str.length();k++){
				if(str[k]>='0'&&str[k]<='9'&&(k+1==str.length())||(str[k+1]<'0'||str[k+1]>'9')){//一组元素带数量 
					string ss;//substring记录该元素 
					int num=0;
					for(int l=boundary;l<=k;l++){
						if(str[l]>='0'&&str[l]<='9'){
							num=num*10+str[l]-'0';
						}
						else{
							ss+=str[l];
						}
					}
					if(find(ve.begin(),ve.end(),sss)==ve.end()) ve.push_back(ss);//目前没有该元素,加入 
					for(int p=0;p<ve.size();p++){
						if(ve[p]==ss){
							ys[p][j]=num;
						}
					}
					boundary=k+1;//更新左边界 
				}
			}
		}
		gs(ys,0,ve.size(),0,m);//数组 行开始 行结束 列开始 列结束
		int ansnum=count(ans,0,ve.size(),0,m);
		if(ansnum<m){
			cout<<"Y"<<endl;
		}
		else{
			cout<<"N"<<endl;
		} 
	}
	return 0;
}

202403-4


暴力混分

//可以使用链表存储,链表加暴力听说可以AC
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAX=3e5+5;
int c,m,n;
int wat[MAX]={0};

void pd(){
	bool flag=false;
	for(int i=1;i<=c;i++){
		if(wat[i]>4){//需要操作 
			flag=true;//进行操作
			wat[i]=0;
			int lll=i-1,rrr=i+1;
			while(lll>=1){//向左,从左开始遍历 
				if(wat[lll]){
					wat[lll]++;
					break;
				}
				lll-=1;
			}
			while(rrr>=1){//向右 
				if(wat[rrr]){
					wat[rrr]++;
					break;
				}
				rrr+=1;
			}
			break;
		}
	}
	if(flag)pd();
	return;
}

int main(){
	cin>>c>>m>>n;//网格宽度 有水的格子 操作次数 
	for(int i=1;i<=m;i++){
		int x,w;
		cin>>x>>w;
		wat[x]=w;
	}
	for(int i=1;i<=n;i++){
		int p;
		cin>>p;
		wat[p]++;//p格子的水加一 
		pd();
		int cnt=0;
		for(int i=1;i<=c;i++){
			if(wat[i])cnt++;
		}
		cout<<cnt<<endl;
	}
	return 0;
}
posted @ 2024-04-06 15:50  skdtxdy  阅读(170)  评论(3编辑  收藏  举报