蓝桥杯(准备)

t1:题目链接:扫雷 - 题目 - Daimayuan Online Judge

前置知识:

  • 二维坐标压缩为一维坐标:将(x,y)最大值+1看成n进制,那么坐标(x,y)就可以化为x*n+y(一维)
  • 哈希函数:将一个一个long long的值可以转化为一个int类型的操作(这个题好像只能用手写哈希函数转化,据说会比unordered快好几倍,用unordered_map好像时间复杂度上过不了unordered_map)

思路:

首先这个地图上可能会有重合的地雷,用并查集历遍也不行(需要对各个点之间建边,而且这个图中的边是有向的,(在有包含情况下)总是从半径大的雷指向半径小的雷),由于x,y<=1e9,如果采用二维坐标存图显然是不行的,这个时候需要将坐标压缩为一维(坐标变成了 long long),然后用哈希函数(总的点数的倍数越大越好,但也不能超过限度)将long long 的数据对应为Int 数据。

对于出现在同一个点的地雷可以用一个cnt[]数组记录下该点的总雷数,然后爆炸半径取这个点地雷中最大的。

最后,由于r<10用一个dfs或bfs历遍整个图就可。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
//手写哈希表+图的历遍
const int M=999997,b=1e9+1;
//M是哈希值(M=N*10),N是存的地雷的个数,b是将二维坐标转化为一位坐标的进制
int n,m,r[M];//记录该点的爆炸半径
ll h[M];//存哈希表,必须开long long,因为二维转化后的一维坐标是long long
int ans,cnt[M];//ans记录答案,cnt[i]记录该点的地雷数
ll get_key(int x,int y){//将二维坐标转换为一维的long long
	return (ll)x*b+y;
}
//手写hash函数
int find(int x,int y){//将一维坐标转化为唯一int类型
	ll key=get_key(x,y);
	int t=(key%M+M)%M;//加M的原因防止下标是负数
	while(h[t]!=-1&&h[t]!=key){
		if(++t==M)t=0;//越界了,重新从0开始
	}
	return t;
}
int s(int x){return x*x;}
void dfs(int x,int y,int l){
//由于搜圆不好搜
    //先对中心为x,y,边长为2l的矩形进行搜索,排除圆以外的
	for(int i=x-l;i<=x+l;i++){
		for(int j=y-l;j<=y+l;j++){
			if(cnt[find(i,j)]&&s(i-x)+s(j-y)<=s(l)){//搜寻有雷的点以及圆形内的点
				ans+=cnt[find(i,j)];
				cnt[find(i,j)]=0;//这个点已经搜索过了,将这个点的雷清空
				dfs(i,j,r[find(i,j)]);
			}
		
		}
	}
}
int main()
{
	cin>>n>>m;
	memset(h,-1,sizeof(h));//初始化哈希表
	for(int i=1;i<=n;i++)
	{
		int x,y,R;
		scanf("%d%d%d",&x,&y,&R);
		ll t=get_key(x,y);
		h[find(x,y)]=t;
		cnt[find(x,y)]++;//统计该点地雷数
		r[find(x,y)]=max(r[find(x,y)],R);//该点爆炸半径取最大的
	}
	for(int i=1;i<=m;i++){
		int x,y,R;
		scanf("%d%d%d",&x,&y,&R);
		dfs(x,y,R);
	}
	cout<<ans<<endl;

 	return 0;
}

T2:修减灌木http://oj.daimayuan.top/course/18/problem/750

找规律:

对于3棵树的情况: 4 2 4

对于4棵树的情况: 6 2 2 6

对于5棵树的情况: 8 6 4 6 8

。。。。。。。

好成功找到了规律:对于第i棵树(i<=n/2):(n-i),然后关于中间棵树对称

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cout<<max(n-i,i-1)*2<<endl;//规律
	}
 	return 0;
}

T3:X进制减法X 进制减法 - 题目 - Daimayuan Online Judge

这道题很明显的贪心策略:

对于每一位的数字a和b,想要最后x-y最小,显然要每一位的进制都是最小,才能使x-y最小,故每一位的进制取max(a,b)+1,然后特判一下小于1的情况,让它是二进制;

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1000000007;
int n,a,b;
int x[1000005],y[100005],num[100005];

int main()
{
	cin>>n;
	cin>>a;
	for(int i=a-1;i>=0;i--)cin>>x[i];
	cin>>b;
	for(int i=b-1;i>=0;i--)cin>>y[i];
	int m=max(a,b);
	for(int i=m-1;i>=0;i--){
		num[i]=max(x[i]+1,y[i]+1);//贪心
		num[i]=max(num[i],2);//特判一下小于2的情况
	}
	ll s=0;
	for(int i=m-1;i>=0;i--){
		s=(s*num[i]+x[i]-y[i])%mod;
	}
	cout<<s<<endl;
 	return 0;
}

T4:积木画积木画 - 题目 - Daimayuan Online Judge

状态转移:f[i]=2*f[i-1]+f[i-3](n>=3)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX=1e7+5,mod=1e9+7;
int n;
long long f[MAX],g[MAX];
int main()
{
	cin>>n;
	f[1]=1;f[2]=2;f[3]=5;
	for(int i=4;i<=n;i++){
		f[i]=(2*f[i-1]+f[i-3])%mod;
	}
	cout<<f[n]<<endl;

 	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值