2023年多校联训NOIP层测试1

闲来无事,补个博客。题目全是COCI的原题


T1 打字( 50 p t s 50pts 50pts)

题目

题目传送门
image

思路

字符串处理,注意所有情况如: B 是一个名字,B1 不是。

code

#include<bits/stdc++.h>
using namespace std;
int sum,o,m,ans[10010],cnt=1;
char s[10010];
signed  main(void){
	scanf("%d",&o);
	while(scanf("%s",s+1)!=EOF){
		//cout<<(s+1)<<endl;
		int n=strlen(s+1);
		int f=(s[1]>='A'&&s[1]<='Z');
		if(f) for(int i=2;i<n;++i) if(!(s[i]>='a'&&s[i]<='z')) f=0;//是否有不是数字的
		if((s[n]=='.'||s[n]=='?'||s[n]=='!')){
			printf("%d\n",sum+f);
			sum=0;
		}
		else if(f&&((s[n]>='a'&&s[n]<='z')||(n==1))) ++sum;
	}
	return 0;
}

T2 下棋( 6 p t s 6pts 6pts)

COCI原题:pohlepko

题目

image

思路

50 p t s 50pts 50pts
贪心
因为数据规定每个格子右边和下边的两个英文字母不同,依次选择字典序最小的字母即可。

70 p t s 70pts 70pts
搜索

100 p t s 100pts 100pts
枚举
对于每一步,步数相同时,坐标 ( x , y ) (x,y) (x,y), x + y x+y x+y 的值相同。所以基本思路是:

枚举每一步中的所有字母,同时需要判断上一步是否可到达(才能走到当前位置),选出其中字典序最小的,标记这些位置是可达
的,这些位置可以进行扩展。

code

#include<bits/stdc++.h>
using namespace std;
const int N=2e3+10;
int y,n,m;
char a[N][N];
bool vis[N][N];
signed main(void){
	scanf("%d%d",&n,&m);
	memset(a,'z',sizeof a);
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			cin>>a[i][j];
		}
	}
	cout<<a[1][1];
	vis[1][1]=1;
	for(int i=2;i<=n+m-1;++i){
		char o='z';
		for(int j=1;j<=n;++j){
			y=i-j+1;
			if(y>=1&&y<=m){
				if(vis[j-1][y]&&a[j][y]<o) o=a[j][y];				
				if(vis[j][y-1]&&a[j][y]<o) o=a[j][y];				
			}
		}
		cout<<o;
		for(int j=1;j<=n;++j){
			y=i-j+1;
			if(y>=1&&y<=m){
				if(vis[j-1][y]&&a[j][y]==o) vis[j][y]=1;				
				if(vis[j][y-1]&&a[j][y]==o) vis[j][y]=1;			
			}
		}
	}
	return 0;
}

T3 分钱( 0 p t s 0pts 0pts)

题目传送门

题目

image

思路

image
image

code

#include<bits/stdc++.h>
using namespace std;
int n,a[550],dp[550][100001],sum;
signed main(void){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d",a+i);
		sum=sum+a[i];
	}
	memset(dp,-0x3f,sizeof dp);
	dp[0][0]=0;
	for(int i=1;i<=n;++i){
		for(int j=0;j<=sum;++j){
			dp[i][j]=dp[i-1][j];
			dp[i][j]=max(dp[i][j],dp[i-1][abs(j-a[i])]+a[i]);
			dp[i][j]=max(dp[i][j],dp[i-1][j+a[i]]+a[i]);
		}
	}
	printf("%d\n",sum-dp[n][0]/2);
	return 0;
}

T4 超级英雄( 0 p t s 0pts 0pts)

题目传送门

题目

image

思路

(闲话:因为出题人直接把他原题的英文全部扔进了百度翻译,把 左右相邻或上下相邻,即四连通 翻译成了 并排相邻。让我喜提此题爆 0 0 0。)

image

在luogu过得在accoders上被卡的代码

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
int qqqq,n,m,k;
struct node{int x,y;};
bool vis[41],pd[N][N];
int co[N][N],kkkkk,dis[41][N][N];
vector<node>qq[41];
queue<node>q;
inline void bfs(int o){
	memset(vis,0,sizeof vis);
	memset(pd,0,sizeof pd);
	for(node i:qq[o]){
		int x=i.x,y=i.y;
		dis[o][x][y]=0;
		q.push(i);
		pd[x][y]=1;
	}
	vis[o]=1;
	while(!q.empty()){
		int x=q.front().x,y=q.front().y,w=co[x][y],u=dis[o][x][y];
		q.pop();
		if(!vis[w]){
			vis[w]=1;
			for(node i:qq[w]){
				int xx=i.x,yy=i.y;
				if(!pd[xx][yy]){
					dis[o][xx][yy]=u+1;
					q.push(node{xx,yy});
					pd[xx][yy]=1;
				}
			}
		}
		for(int i=0;i<4;++i){
			int xx=x+dx[i],yy=y+dy[i];
			if(xx>0&&xx<=n&&yy>0&&yy<=m&&!pd[xx][yy]){
				q.push(node{xx,yy});
				dis[o][xx][yy]=u+1;
				pd[xx][yy]=1;
			}
		}
	}
	return ;
} 
signed main(void){
	//mt19937 rnd(random_device{}());
	//memset(dis,-1,sizeof dis); 
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			scanf("%d",&co[i][j]);
			qq[co[i][j]].push_back((node){i,j});
//			if(i==1&&j==1) kkkkk=co[i][j];
//			if(kkkkk!=co[i][j]) kkkkk=-1;
		}
	}
	for(int i=1;i<=k;++i){
		bfs(i);
	}
	scanf("%d",&qqqq);
	for(int ans,r1,c1,r2,c2,i=1;i<=qqqq;++i){
		scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
		ans=abs(r1-r2)+abs(c1-c2);
//		if(r1==r2&&c1==c2){printf("0\n");continue;}
//		else if(kkkkk!=-1){printf("1\n");continue;}
//		else if(co[r1][c1]==co[r2][c2]){printf("1\n");continue;}
		for(int i=1;i<=k;++i){
			ans=min(ans,dis[i][r1][c1]+dis[i][r2][c2]+1);
		}
		printf("%d\n",ans);
	}
	return 0;
}

卡常后的代码

点击查看代码
#include<bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
using namespace std;
inline int Min(int x,int y){return x<y? x:y;}
inline int Abs(int x){return x<0? -x:x;}
inline int read(){
    int x=0;
    bool f=true;
    char s=getchar();
    for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=false;
    for(;'0'<=s&&s<='9';s=getchar()) x=(x<<1)+(x<<3)+(s^48);
    return f? x:-x;
}
#define read read()
void write(int x){
    if(x<0) x=-x,putchar('-');
    if(x>9) write(x/10);
    putchar(x%10+48);
}
int n,m,k,a[1010][1010],color[50];
vector<int> x[50],y[50];
int dist[50][1010][1010],dx[]={-1,0,1,0},dy[]={0,1,0,-1};
struct myqueue{
    int q[1000000];
    int l=1,r=1;
    inline void push(int x){
        q[++r]=x;
    }
    inline int front(){
        return q[l+1];
    }
    inline void pop(){
        l++;
    }
    inline int back(){
        return q[r];
    }
    inline bool empty(){
        return r<=l;
    }
};
signed main(){
    n=read,m=read,k=read;
    int i,j,c;
    for(i=1;i<=n;++i){
        for(j=1;j<=m;++j){
            a[i][j]=read;
            ++color[a[i][j]];
            x[a[i][j]].push_back(i);
            y[a[i][j]].push_back(j);
        }
    }
    for(c=1;c<=k;++c){
        myqueue qx,qy;
        bool vis[41]={false};
        vis[c]=true;
        for(i=0;i<color[c];++i){
            qx.push(x[c][i]);
            qy.push(y[c][i]);
            dist[c][qx.back()][qy.back()]=1;
        }
        while(!qx.empty()){
            int i=qx.front(),j=qy.front();
            qx.pop();qy.pop();
            for(register int l=0;l<4;++l){
                int nx=i+dx[l],ny=j+dy[l];
                if(1>nx||nx>n||1>ny||ny>m) continue;
                if(!dist[c][nx][ny]){
                    qx.push(nx);
                    qy.push(ny);
                    dist[c][qx.back()][qy.back()]=dist[c][i][j]+1;
                }
            }
            if(!vis[a[i][j]]){
                int colour=a[i][j];
                vis[colour]=true;
                for(register int l=0;l<color[colour];++l){
                    if(!dist[c][x[colour][l]][y[colour][l]]){
                        qx.push(x[colour][l]);
                        qy.push(y[colour][l]);
                        dist[c][x[colour][l]][y[colour][l]]=dist[c][i][j]+1;
                    }
                }
            }
        }
    }
    int Q=read,ans;
    while(Q--){
        int x1=read,y1=read,x2=read,y2=read;
        ans=Abs(x1-x2)+Abs(y1-y2);
        for(register int i=1;i<=k;++i){
            ans=Min(ans,dist[i][x1][y1]+dist[i][x2][y2]-1);
        }
        write(ans);
        putchar('\n');
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值