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

目录

A 距离和

代码:

B 扩散

解析:

代码:

C 错误票据

解析:

代码:

D 倍数问题

解析:

代码:




A 距离和

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;

int main() {
    int s=('L'-'A')+('N'-'L')+('Q'-'L')+('L'-'I')+('L'-'A')+('O'-'L')+('N'-'A')+('Q'-'A')+('I'-'A')+('O'-'A')+('Q'-'N')+('N'-'I')+('O'-'N')+('N'-'A')+('Q'-'I')+('Q'-'A')+('Q'-'O')+('I'-'A')+('O'-'I')+('O'-'A');
    cout<<s; 
    return 0;
}

B 扩散

解析:

        这道题有很多种方法(暴力、DFS、BFS)。博主只用BFS实现,提供暴搜的思路,代码留给读者去实现吧。

        暴力:因为题目说2020分钟后,且一个黑方格往四周扩散一个单位,假如一个点(2020,2020)直向上扩散,2020min后扩散到(0,2020)。假如(2,2)向对角扩散,即扩散到(0,0),我们可以发现它的顺序是(2,2)->(2,1)->(1,1)->(0,1)->(0,0)(这是其中一种),需要4步。所以我们可以得到一条公式:已知一个点(a,b),它可以扩散到的点就是fabs((x-a)+(y-b))<=2020中的(x,y).利用这条公式循环即可。

        BFS:直接套模板,详情见代码。

代码:

//BFS
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
int sum,vis[10000][10000];//用vis存步长+标记
const int dr[]= {0,0,1,-1};
const int dc[]= {1,-1,0,0};

struct node {
	int x,y;
	node(int x=0, int y=0):x(x),y(y) {}
};

queue<node> q;

bool inside(int xx,int yy) {
	if(xx>=10000 || xx<0 || yy>=10000 || yy<0) return false;
	else return true;
}

void bfs() {
	q.push(node(5000,5000));
	q.push(node(7020,5011));
	q.push(node(5011,5014));
	q.push(node(7000,7000));
	vis[5000][5000]=vis[7020][5011]=vis[5011][5014]=vis[7000][7000]=1;//这里是起点所以下面是2021
		while(!q.empty()) {
		node u=q.front();
		q.pop();
		if(vis[u.x][u.y]==2021) return;
		for(int i=0; i<4; i++) {
			int nx=u.x+dr[i];
			int ny=u.y+dc[i];
			if(inside(nx,ny) && !vis[nx][ny]) {//记得限界,不然死循环
				vis[nx][ny]=vis[u.x][u.y]+1;
				node v(nx,ny);
				q.push(v);
			}
		}	
	}
}

int main() {
	LL s=0;
	bfs();
	for(int i=1000; i<10000; i++)
	for(int j=1000; j<10000; j++)
	if(vis[i][j]>0) s++;
	cout<<s;
	return 0;
}

C 错误票据

 

解析:

        这道题就是一道简单模拟题,不过它难在输入上。这个题的输入不是一个一个数输入,而是一行一行输入,有人就会说用字符串就好了,没错!就是字符串,由于它有空格,所以要用到getline,并且需要用getchar吃回车。

        直到怎么输入字符串后,我们需要将这些字符串转成一个个数存到数组中,由于它是一行数,每个数间有空格,所以我们只能通过空格来存数进数组。

        最后,我们排完序对比一下就能知道断号和重号了。

代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
int a[10010],nn,s1,s2;

void fenjie(string ss) {
	int res=0,n=0;
	for(int i=0; i<ss.size() ; i++) {
		if(ss[i]==' ') a[++nn]=res,res=0;
		else res=res*10+(ss[i]-'0');
	}
}

int main() {
	int n;
	cin>>n;
	getchar();//吃回车
	for(int i=0; i<n; i++) {//n行
		string s;
		getline(cin,s);//getline吃空格
		s+=" ";//用空格来判定完整的一个数
		fenjie(s);//将这一串串数字都转成int存入数组
	}
	sort(a+1,a+nn+1);//进行排序来找出错误票据

	for(int i=1; i<nn; i++) {
		if(a[i]==a[i+1]) s1=a[i];//重复 
		if(a[i]!=a[i+1] && a[i]+1!=a[i+1]) s2=a[i]+1;//错误 
	}
	//for(int i=1; i<=nn; i++)
	//if(a[i]>0) cout<<a[i]<<" ";
	//cout<<endl;
	cout<<s2<<" "<<s1;
	return 0;
}

D 倍数问题

 

解析:

        这道题在day5的时候做过(不过当时博主没做),当时没有写题解,比较忙,现在每天要有空都会写,唠完家常,接下来让我们分析一下题意。

        这道题要我们求和为K的倍数且和为最大值,那么我们首先得取出3个数字使其和为K的倍数。大概思路:找出三个数 mod k相加后再mod k=0(本题难点),然后比较出最大值就行了,那么问题来了:这样岂不是要相加很多遍?这样时间复杂度高达10^15。当然不是全都取模然后再取模。题目说到和为最大,那我们只需要对其进行排序,然后取出其中三个最大值相加判定即可。具体实现和解释已经在代码中。

        

代码:

#include <bits/stdc++.h>
#include <vector>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
vector<int> a[1005];//每个a[i]都是不定长数组(由于存入的数不知道有多少个,如果开a[1005][100000]就有点大了,浪费太多内存)
int n,k,maxn=0;
//从大到小排序 
bool cmp1(int &a,int &b) {
	return a>b;
}

int main() {
	int x,sum;
	cin>>n>>k;
	for(int i=0; i<n; i++) {
		cin>>x;
		a[x%k].push_back(x);//用余数来存关系
	}
	for(int i=0; i<k; i++)
		sort(a[i].begin(),a[i].end(),cmp1);//每堆都要排 

	/*for(int i=0; i<k; i++)
		for(int j=0; j<a[i].size(); j++)
			cout<<a[i][j]<<endl;*/
	//选3个数且和为k的倍数,有几种选法(1,1,1),(3,0,0)=(0,0,3)=(0,3,0),(2,0,1)=(0,2,1),(0,1,2)=(2,1,0),(1,2,0)=(1,0,2)
	for(int i=0; i<k; i++)
		for(int j=0; j<k; j++) {
			int h=(k-(i+j)%k) % k;
			//这堆中需要有数才能取数,不然会出现系统赋值,或者系统无法读取到数值导致输出无效答案 
			if(a[h].size()&&a[j].size()&&a[i].size()) {
				//三堆各选一个(1,1,1)
				if(i!=h && i!=j && j!=h) {
					sum=a[i][0]+a[j][0]+a[h][0];
					maxn=max(maxn,sum);
				}
				//一堆中选三个(3,0,0)=(0,0,3)=(0,3,0)
				if(i==j && j==h && a[i].size()>2) {
					sum=a[i][0]+a[i][1]+a[i][2];
					maxn=max(maxn,sum);
				}
				//有两堆相同,即一堆选两个,另一堆选一个(2,0,1)=(0,2,1)
				if(i==j && i!=h && a[i].size()>1) {
					sum=a[i][0]+a[i][1]+a[h][0];
					maxn=max(maxn,sum);
				}
				//有两堆相同,即一堆选两个,另一堆选一个(0,1,2)=(2,1,0)
				if(i==h && i!=j && a[i].size()>1) {
					sum=a[i][0]+a[i][1]+a[j][0];
					maxn=max(maxn,sum);
				}
				//有两堆相同,即一堆选两个,另一堆选一个(1,2,0)=(1,0,2)
				if(h==j && i!=h && a[h].size()>1) {
					sum=a[h][0]+a[h][1]+a[i][0];
					maxn=max(maxn,sum);
				}
			}
		}
	cout<<maxn;
	return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_谦言万语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值