NOIP2013提高组复赛day2试题解析

发布时间 2023-09-03 21:02:56作者: 天雷小兔

1.

解析:

对于一道题可以先模拟一下他的样例,通过模拟样例发现,总次数正好是每个数与前一个数的差之和,所以就可以得到O(n)复杂度的代码

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5+39+7;
ll n,a[N],ans=0;
int main(){
//	freopen("block.in","r",stdin);
//	freopen("block.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)ans+=(a[i]>a[i-1]?a[i]-a[i-1]:0);
	cout<<ans;
	return 0;
}

  

举一反三:

  这两道题和本题是一样的

2.

解析:

跟上一道题一样,先模拟数据,通过模拟数据发现,本题可转化为求解整数h1,h2,h3,.....,hn中转折点的个数,就得出代码了

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5+39+7;
ll turn=1,h[N],n,ans=0;
int main(){
//	freopen("flower.in","r",stdin);
//	freopen("flower.out","w",stdout);
	cin>>n;
	for(int i=1;i<=n;i++)cin>>h[i];
	if(n==1){
		cout<<1;
		return 0;
	}
	ans=1;turn=h[1]<=h[2];
	for(int i=1;i<=n;i++){
		if(i==n&&!turn){
			ans++;
			continue;
		}
		if(turn){
			if(h[i+1]<h[i]){
				turn=0;
				ans++;
				continue;
			}
		}else{
			if(h[i+1]>h[i]){
				turn=1;
				ans++;
				continue;
			}
		}
	}
	cout<<ans;
	return 0;
}

  

3.

 解析:

如果使用复杂度为O(n^4)的bfs暴力处理,q一大会TLE,这道题可以转化为spfa求最短路的题目,使用mat数组记录地图,dis记录距离,step记录步数,然后使用O(n^4)的预处理,处理出step数组,

在求解答案时,使用spfa求解最短路,最短路的长度即为答案

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 35+39+7,INF = 0x3f3f3f3f,dx[]={0,0,-1,1},dy[]={-1,1,0,0};
int mat[N][N],dis[N][N][4],step[N][N][4][4],d[N][N],n,m,q,T,ex,ey,sx,sy,tx,ty;
struct node{
	int x,y;
};
struct node2{
	int x,y,k;
};
bool isok(int x,int y){
	return (1<=x&&x<=n&&1<=y&&y<=m);
}
int spfa(){
	queue<node2>q;
	for(int k=0;k<4;k++){
		if(dis[sx][sy][k]!=INF){
			q.push((node2){sx,sy,k});
		}
	}
	while(q.size()){
		int x=q.front().x,y=q.front().y,k=q.front().k;q.pop();
		for(int i=0;i<4;i++){
			int xx=x+dx[i],yy=y+dy[i];
			if(isok(xx,yy)&&mat[xx][yy]&&step[x][y][k][i]!=INF){
				if(dis[xx][yy][i^1]>dis[x][y][k]+step[x][y][k][i]+1){
					dis[xx][yy][i^1]=dis[x][y][k]+step[x][y][k][i]+1;
					q.push((node2){xx,yy,i^1});
				}
			}
		}
	}
	int ans=INF;
	for(int i=0;i<4;i++)ans=min(ans,dis[tx][ty][i]);
	return (ans==INF?-1:ans);
}
int bfs(int sx,int sy,int tx,int ty){
	if(!mat[sx][sy]||!mat[tx][ty])return INF;
	memset(d,0x3f,sizeof(d));
	d[sx][sy]=0;
	queue<node>q;
	q.push((node){sx,sy});
	while(q.size()){
		if(d[tx][ty]!=INF)return d[tx][ty];
		int x=q.front().x,y=q.front().y;
		q.pop();
		for(int i=0;i<4;i++){
			int xx=x+dx[i],yy=y+dy[i];
			if(isok(xx,yy)&&mat[xx][yy]&&d[xx][yy]==INF){
				d[xx][yy]=d[x][y]+1;
				q.push((node){xx,yy});
			}
		}
	}
	return INF;
}
void init(){
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			int vis=mat[i][j];mat[i][j]=0;
			for(int k=0;k<4;k++){
				for(int l=0;l<4;l++){
					step[i][j][k][l]=bfs(i+dx[k],j+dy[k],i+dx[l],j+dy[l]);
				}
			}
			mat[i][j]=vis;
		}
	}
}
int solve(){
	cin>>ex>>ey>>sx>>sy>>tx>>ty;
	if(sx==tx&&sy==ty)return 0;
	if(sx==ex&&sy==ey)return -1;
	if(!isok(ex,ey)||!isok(sx,sy)||!isok(tx,ty))return -1;
	if(!mat[ex][ey]||!mat[sx][sy]||!mat[tx][ty])return -1;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			for(int k=0;k<4;k++){
				dis[i][j][k]=INF;
			}
		}
	}
	mat[sx][sy]=0;
	for(int k=0;k<4;k++)dis[sx][sy][k]=bfs(ex,ey,sx+dx[k],sy+dy[k]);
	mat[sx][sy]=1;
	return spfa();
}
int main(){
	cin>>n>>m>>T;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>mat[i][j];
		}
	}
	init();
	while(T--)
		cout<<solve()<<'\n';
	return 0;
}