第三届NOI Online普及组线上比赛赛后总结
其实这次考试又双叒叕爆零了qwq
第三届NOI Online赛后总结
第一题、最急救助
题面
思路
字符串循环取出子串,判断是否为"sos"
预期分数
100分qwq
考试代码
#include<bits/stdc++.h>
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<bits/stdc++.h>
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<bits/stdc++.h>
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;
cnt=0;
sort(b+1,b+k+1,greater<int>());
// for(int i=1;i<=k;i++){
// cout<<b[i]<<" ";
// }
for(int i=1;i<=k;i++){
// sum=0;
// cout<<b[i]<<" ";
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<bits/stdc++.h>
#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<bits/stdc++.h>
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<bits/stdc++.h>
#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;
}
她透过我的血,看到了另一抹殷红