第三届NOI Online普及组线上比赛赛后总结

其实这次考试又双叒叕爆零了qwq

第三届NOI Online赛后总结

  • 第一题、最急救助
    • 题面
    • 思路
    • 预期分数
    • 考试代码
    • AC代码(摘自洛谷大佬题解)
  • 第二题、观星
    • 题面
    • 思路
    • 预期分数
    • 考试代码
    • AC代码(摘自洛谷大佬题解)
  • 第三题、手表
    • 题面
    • 思路
    • 预期分数
    • 考试代码
    • AC代码

第一题、最急救助

题面

洛谷可评测题面

思路

字符串循环取出子串,判断是否为"sos"

预期分数

100分qwq

考试代码

#include
using namespace std;
int n,ma,cnt,k=1;
struct node{
     
	string name;
	string order;
}b[110];
struct ans{
     
	string name;
	int num;
}a[110];
string s[110];
int main(){
     
	cin>>n;
	for(int i=1;i<=n;i++){
     
		cin>>b[i].name>>b[i].order;
		a[i].name=b[i].name;
		for(int j=0;j<b[i].order.size();j++){
     
			if(b[i].order[j]=='s'&&b[i].order[j+1]=='o'&&b[i].order[j+2]=='s'){
     
				a[i].num++;
			}
		}
	}
	for(int i=1;i<=n;i++){
     
		ma=max(a[i].num,ma);
	}
	for(int i=1;i<=n;i++){
     
		if(a[i].num==ma){
     
			cnt++;
			s[k++]=a[i].name;
		}
	}
	if(cnt==1){
     
		cout<<s[1]<<endl;
		cout<<ma;
	}else{
     
		for(int i=1;i<=k;i++){
     
			cout<<s[i]<<" ";
		}
		cout<<endl;
		cout<<ma;
	}
	return 0;
}

AC代码(摘自洛谷大佬题解)

#include
using namespace std;
int n;
struct node{
     
    string name,help;
    int s,num;
    //name 是求助者的名字
    //help 是求助者的求助信息
    //s 是求助信息中子串 sos 的数量
    //num 是求助者的顺序
}str[105];
int find(string qwq){
                        //寻找子串 sos 的数量
    int len=qwq.size();                 //提取出这个字符串的长度,STL 大法好!QwQ
    int anss=0;                         //子串 sos 的数量
    for(int i=0;i<len-2;i++){
                //从头到尾枚举
        if(qwq[i]=='s'&&qwq[i+1]=='o'&&qwq[i+2]=='s'){
       //如果这里有一个 sos
            anss++;                     //子串 sos 的数量+1
        }
    }
    return anss;                        //返回子串 sos 的数量
}
bool cmp(node p,node q){
                     //比较函数 cmp
    if(p.s==q.s){
                            //如果两个求助信息中的子串 sos 的数量都相同
        return p.num<q.num;             //按照输入顺序排序
    }
    return p.s>q.s;                     //否则按照求助信息中的子串 sos 的数量排序
}
int main(){
     
    //freopen("save.in","r",stdin);
    //freopen("save.out","w",stdout);
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);                        //黑科技cin,cout加速
    cin>>n;
    for(int i=1;i<=n;i++){
     
        cin>>str[i].name>>str[i].help;
        str[i].s=find(str[i].help);     
        str[i].num=i;
    }
    sort(str+1,str+n+1,cmp);            //STL 大法好!QWQ
    int tmp=str[1].s;                   //排序之后,最前面的那个自然就是子串 sos 最多的啦QwQ,直接记录即可。
    for(int i=1;i<=n;i++){
     
        if(str[i].s!=tmp){
                   //如果子串 sos 的数量少于 tmp
            break;                      //立刻退出循环停止输出
        }
        cout<<str[i].name<<" ";
    }
    cout<<endl<<tmp;                    //别忘了换行哦
    return 0;
}

第二题、观星

题面

洛谷可评测题面

思路

使用bfs求连通块,再根据连通块的星星个数求出星系个数

预期分数

60分左右qwq

考试代码

当时考试太弱智做超时了qwq

#include
using namespace std;
int n,m,cnt,k=1,sum,ma;
char a[2010][2010];
bool vis[2010];
int fx[]={
     0,0,1,0,-1,-1,-1,1,1};
int fy[]={
     0,1,0,-1,0,1,-1,1,-1};
int b[2010];
bool f;
void dfs(int x,int y,int cnt){
     
	f=false;
//	vis[x][y]=true;
	a[x][y]='.';
	for(int i=1;i<=8;i++){
     
		if(a[x+fx[i]][y+fy[i]]=='*'){
     
			f=true;
			break;
		}
	}
	if(!f){
     
		b[k++]=cnt;
		return;
	}
	int dx,dy;
	for(int i=1;i<=8;i++){
     
		dx=x+fx[i];
		dy=y+fy[i];
		if(a[dx][dy]=='*'/*&&!vis[dx][dy]*/){
     
			dfs(dx,dy,cnt+1);
		}
	}
}
int main(){
     
	freopen("star.in","r",stdin);
	freopen("star.out","w",stdout); 
	cin>>n>>m;
	for(int i=1;i<=n;i++){
     
		for(int j=1;j<=m;j++){
     
			cin>>a[i][j];
		}
	}
	for(int i=1;i<=n;i++){
     
		for(int j=1;j<=m;j++){
     
			if(a[i][j]=='*'){
     
				cnt++;
				dfs(i,j,0);
			}
		}
	}
//	cout<
	cnt=0;
	sort(b+1,b+k+1,greater<int>());
//	for(int i=1;i<=k;i++){
     
//		cout<
//	}
	for(int i=1;i<=k;i++){
     
//		sum=0;
//		cout<
		if(b[i]==b[i+1]){
     
			cnt++;
			sum+=b[i]+b[i+1];
			vis[i]=true;
			vis[i+1]=true;
			ma=max(ma,sum);
		}
	}
	for(int i=1;i<=k;i++){
     
		if(!vis[i]){
     
			cnt++;
		}
	}
	cout<<cnt<<" "<<ma;
	fclose(stdin);
	fclose(stdout);
	return 0;
}

AC代码(摘自洛谷大佬题解)

#include
#define N 1502
using namespace std;
int n,m,dx[8]={
     0,0,1,1,1,-1,-1,-1},dy[8]={
     1,-1,1,0,-1,1,0,-1};//dfs八个方向的模板
int galaxy[N*N],sum,Max;
bool star[N][N];//用于存储每个坐标是否有星星
void Search(int x,int y){
     //dfs
	sum++;//储存搜索到的这个星座的星星数量
	star[x][y]=false;//设为已访问过
	for(int i=0;i<8;i++){
     //八个方向
		int xx=x+dx[i],yy=y+dy[i];
		if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&star[xx][yy])
			Search(xx,yy);
	}
}
int main(){
     
//	freopen("star.in","r",stdin);
//	freopen("star.out","w",stdout);
	char c;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
     //将输入结果存入star数组
		for(int j=1;j<=m;j++){
     
			cin>>c;
			if(c=='*')star[i][j]=true;
		}
	}
	for(int i=1;i<=n;i++){
     
		for(int j=1;j<=m;j++){
     
			if(star[i][j]){
     
				Search(i,j);
				galaxy[sum]++;
				if(sum*galaxy[sum]>Max)Max=sum*galaxy[sum];//用于计算最大的星系,sum*galaxy[sum]的意义详见上面
				sum=0;
			}
		}
	}
	int ans=0;
	for(int i=0;i<=n*m;i++){
     
		if(galaxy[i])ans++;//用于计算星系的数量
	}
	cout<<ans<<' '<<Max;
	return 0;
}

第三题、手表

题面

洛谷可评测题面

思路

使用二进制优化将多重背包转化为01背包再求解

预期分数

50分awa

考试代码

#include
using namespace std;
int n,m,ma;
struct node{
     
	int k,a;
}arr[210];
bool f[500010];
int t[100010];
//f[j]=f[j]|f[j-w[i];
int main(){
     
	freopen("watch.in","r",stdin);
	freopen("watch.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
     
		cin>>arr[i].k>>arr[i].a;
		arr[i].a=arr[i].a*arr[i].k;
	}
	for(int i=1;i<=m;i++){
     
		cin>>t[i];
		ma=max(ma,t[i]);
	}
	f[0]=true;
	for(int j=1;j<=n;j++){
     
		for(int x=ma;x>=arr[j].k;x--){
     
			f[x]=f[x]|f[x-arr[j].k];
		}		
	}
	for(int i=1;i<=m;i++){
     
		if(f[t[i]]==true)cout<<"Yes\n";
		else cout<<"No\n";
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}

AC代码

#include
#define maxn 205
#define ll long long
using namespace std;
int n,m,x,cnt;
ll k[maxn],a[maxn],v[maxn*20],dp[500005];
int main(){
     
    cin>>n>>m;
    for(int i=1;i<=n;i++){
     
    	cin>>k[i]>>a[i];
        for(int j=1;j<=a[i];j<<=1){
     
            v[++cnt]=j*k[i];
            a[i]-=j;
        }
        if(a[i])v[++cnt]=a[i]*k[i];
    }
    dp[0]=0;
    for(int i=1;i<=cnt;i++){
     
        for(int j=500000;j>=v[i];j--){
     
            dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
        }
    }
    while(m--){
     
        cin>>x;
        if(dp[x]==x)cout<<"Yes\n";
        else cout<<"No\n";
    }
	return 0;
}

你可能感兴趣的:(C++,#NOI,Online测试,#洛谷,dfs,字符串)