蓝桥杯31天冲刺打卡(day31)

        Hello,大家好!不知不觉就已经到第31天了(昨天比较忙所以没更题解),明天就要蓝桥杯比赛,有些小伙伴可能会像博主这样有考前焦虑症,这很正常,不过要懂得放松和调整状态,要相信:我们都坚持练了31天的题了,啥题没见过?相信自己该会的都已经会了。在此祝愿大家考到自己理想的成绩,全体省一进军国赛!

        今日份题解已到达,请小伙伴们接收。

目录

1.马的遍历

解析:

2.切绳子

解析:

3.导弹拦截


1.马的遍历

解析:

        一道BFS模板题,直接套模板就好啦,记得这是中国象棋,马走日(不知道的小伙伴记得去看看中国象棋的规则,身为中国人可不能不会中国象棋啊!)

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000009
using namespace std;
typedef long long LL;
//马走日
const int dr[8]= {2,2,1,1,-2,-2,-1,-1};
const int dc[8]= {1,-1,2,-2,1,-1,2,-2};
int n,m,x,y;
int vis[405][405];

struct node {
	int x,y,dis;
	node(int x,int y,int dis):x(x),y(y),dis(dis) {}
};
queue<node> q;
void bfs() {
	node u(x,y,0);
	vis[x][y]=0;
	q.push(u);
	while(!q.empty()) {
		node u=q.front();
		q.pop();
		for(int i=0; i<8; i++) {
			int nx=u.x+dr[i];
			int ny=u.y+dc[i];
			if(nx<1 || nx>n || ny<1 || ny>m || vis[nx][ny]!=-1) continue;//边界
			int diss=u.dis+1;
			vis[nx][ny]=diss;
			node v(nx,ny,diss);
			q.push(v);
		}
	}
}


int main() {
	cin>>n>>m;
	cin>>x>>y;
	memset(vis,-1,sizeof(vis));//没到达的地方输出-1
	bfs();
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=m; j++)
			printf("%-5d",vis[i][j]);//左顶格,边宽为5
		cout<<endl;
	}
	return 0;
}


2.切绳子

解析:

        这是一道浮点二分题。注意输出是两位小数,不用四舍五入。浮点二分while的条件开到1e-8就足够小了,没必要开到1e-12,开到1e-12会T。这里的小数需要截掉,不可以四舍五入,所以我们用sprintf强制将小数点后三位小数转成字符串,然后在第三位小数上加个‘\0’结束符,最后输出字符串。

        当然浮点二分不熟的同学可以转成整数来做,将这些数*100就好,两种代码都在下面了。

//浮点二分
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000009
using namespace std;
typedef double D;
int n,k;
D a[10010];
char s[200];
bool check(D x) {
	int sum=0;
	for(int i=1; i<=n; i++) 
		sum+=a[i]/x;
	return sum>=k;
}

int main() {
	cin>>n>>k;
	D l=0.0,r=0.0;
	for(int i=1; i<=n; i++) {
		cin>>a[i];
		r+=a[i];
	}
	while(r-l>1e-8) {
		D mid=(l+r)/2.0;
		if(check(mid)) {
			l=mid;
		} else r=mid;
	}
    sprintf(s+1,"%.3f",l);
    s[strlen(s+1)]='\0';
    printf("%s",s+1);
	return 0;
}

//整数二分
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000009
using namespace std;
typedef long long LL;
int n,k;
double a[10010];//输入是浮点数
LL b[10010];//防止精度溢出

bool check(double x) {
	int sum=0;
	for(int i=1; i<=n; i++) 
		sum+=b[i]/x;
	return sum>=k;//多了证明每一段小了,往右边
}

int main() {
	cin>>n>>k;
	double ans;
	LL l=0,r=0;//每个*100会让每个数最大值是1e7,再相加肯定爆int,所以要LL
	for(int i=1; i<=n; i++) {
		cin>>a[i];
		b[i]=a[i]*100;//将浮点数转成整数
		r+=b[i];
	}
	while(l<=r) {
		double mid=(l+r)/2.0;//浮点数用于极端数据
		if(check(mid)) {
			ans=mid;
			l=mid+1;
		} else r=mid-1;
	}
	//也可以写double s=ans/100,cout<<ans; 
	printf("%.2f",double(ans/100.0));//除以100.0就可以将其转成浮点数了 
	return 0;
}

3.导弹拦截

解析:

        这是一道最长上升子序列(不上升),可用DP,不过只能过一半数据,还记得前几天的那道“蓝桥骑士”吗?那题和这题一样,也可用DP,不过不能AC,所以这题同理需要用二分+贪心。

        这个题的第一问求的是最长不上升子序列,第二问求的是最长上升子序列,理论上来说是可以用lower_bound和upper_bound来做的,只可惜我的功力不足,用了这俩做了12分,所以就手写二分查找了,手写二分查找的道路可谓是非常坎坷啊!

        第一问:最长不上升子序列。如果小于等于low中最小的元素就进low,如果大于就找low中第一个小于等于n(需要进low的元素)的位置。由于这个是最长不上升子序列,所以从左到右是从大到小(左边最大,右边最小),第一个小于等于n应该是往小的找(右边),所以我们判定条件时尽量将n放在右边,也就是说low[mid] >= n,mid是中间的位置,n比小于等于的话就在右边,在右边就应该往右边找,也就是l = mid + 1。

        第二问:最长上升子序列。如果大于low中最大的元素就进low,如果小于等于的话就找low中第一个大于n(需要进low的元素)的位置。由于这是最长上升子序列(严格单增),所以左小右大,我们需要找第一个大于n的值,应该往大的找(右边),所以我们判定条件时就应该将n置于右边,也就是low[mid] < n,mid是中间的位置,n比它大的话就在右边,在右边也就往右边找,即l = mid+1.

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000009
using namespace std;
typedef long long LL;
int n,low[100010],a[100010];
int ans,cnt;

int main() {
	int s=0;
	memset(low,0,sizeof(low));
	while(scanf("%d",&n)!=EOF) {
		a[++s]=n;
	}
	ans=cnt=1;
	low[1]=a[1];
	for(int i=2; i<=s; i++) {
		if(a[i]<=low[ans]) low[++ans]=a[i];
		else {
			int l=1,r=ans;
			while(l<r) {
				int mid=(l+r)/2;
				if(low[mid]>=a[i]) 
					l=mid+1;
				else r=mid;
			}
			low[r]=a[i];
		}
	}
	memset(low,0,sizeof(low));
	low[1]=a[1];
	for(int i=2; i<=s; i++) {
		if(a[i]>low[cnt]) low[++cnt]=a[i];
		else {
			int l=1,r=cnt;
			while(l<r) {
				int mid=(l+r)/2;
				if(low[mid]<a[i]) l=mid+1;
				else r=mid;
			}
			low[r]=a[i];
		}
	}
	cout<<ans<<endl<<cnt;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_61017400/article/details/124012263
今日推荐