- 黄乾峻 的博客
7月Day8
- @ 2025-7-22 19:53:40
T1 一千万零一只斑点狗
题意:
有1-10000001只狗,每只狗都有自己的编号,给定一个N,让我们求这个数对应的编号。
思路:
根据这个题意,可以推公式,大概意思是将这个数除以26,取余,然后如果这个新得到的数大于26,继续除以26.
代码:
#include<bits/stdc++.h>
using namespace std;
string d(long long N){
string r;
while(N>0){
N--;
char c='a'+(N%26);
r+=c;
N/=26;
}
reverse(r.begin(),r.end());
return r;
}
int main(){
freopen("dog.in","r",stdin);
freopen("dog.out","w",stdout);
long long N;
cin>>N;
cout<<d(N)<<endl;
return 0;
}
T2 金字塔
题意:
根据这个金字塔的信息,可以求出中心坐标和高度。
思路:
向外每移动一格,海拔减1。已知点N的坐标和海拔高度进行反推求出其他值。若 hi=0,则 H≤∣xi−CX∣+∣yi−CY∣。但是CX,CY范围比较小,可以枚举。检查所有点是否满足条件,如果满足则输出结果。
代码:
#include<bits/stdc++.h>
using namespace std;
struct P{
int x,y,h;
};
int main(){
freopen("tower.in","r",stdin);
freopen("tower.out","w",stdout);
int N;
cin>>N;
vector<P>p(N);
for(int i=0;i<N;i++){
cin>>p[i].x>>p[i].y>>p[i].h;
}
for(int cx=0;cx<=100;cx++){
for(int cy=0;cy<=100;cy++){
int H=-1;
for(const auto & t:p){
if(t.h>0){
int e=t.h+abs(t.x-cx)+abs(t.y-cy);
if(H==-1){
H=e;
}else if(H!=e){
H=-1;
break;
}
}
}
if(H==-1) continue;
bool d=true;
for(const auto & t:p){
int c=max(H-abs(t.x-cx)-abs(t.y-cy),0);
if(c!=t.h) {
d=false;
break;
}
}
if(d){
cout<<cx<<" "<<cy<<" "<<H<<endl;
return 0;
}
}
}
return 0;
}
T3 走迷宫
题意:
给定一个N×M的网格迷宫,其中#表示墙,.表示可通行的路。允许在相邻的上下左右四个方向移动,但不能穿过墙或走出迷宫边界。要求找到所有可能的起点和终点组合中,最短路径的最大步数1。
思路:
迷宫的最短路径问题通常使用广度优先搜索解决,因为BFS能保证找到最短路径,而且DFS时间复杂度太高。本题需要枚举所有可能的起点和终点,计算它们之间的最短路径,并取其中的最大值。对每个可通行的点作为起点,执行计算到其他所有点的最短距离。在每次完成后,更新全局的最大步数。
代码:
#include<bits/stdc++.h>
using namespace std;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
int main(){
freopen("maze.in","r",stdin);
freopen("maze.out","w",stdout);
int N,M;
cin>>N>>M;
vector<string> d(N);
for(int i=0;i<N;i++){
cin>>d[i];
}
int m=0;
for(int i=0;i<N;i++){
for(int j=0;j<M;j++){
if(d[i][j]=='.'){
vector<vector<int>> t(N,vector<int>(M,-1));
queue<pair<int,int>>q;
q.push({i,j});
t[i][j]=0;
while(!q.empty()){
auto[x,y]=q.front();
q.pop();
for(int k=0;k<4;k++){
int nx=x+dx[k];
int ny=y+dy[k];
if(nx>=0 && nx<N && ny>=0 && ny<M && d[nx][ny]=='.' && t[nx][ny]==-1){
t[nx][ny]=t[x][y]+1;
q.push({nx,ny});
m=max(m,t[nx][ny]);
}
}
}
}
}
}
cout<<m<<endl;
return 0;
}
T4 划分问题
题意:
给定N道题目(N为偶数),每道题目的难度用整数d表示。需要选择一个整数K,将题目划分为两组:难度大于等于K的题目和普及组两组题目数量相等(各占一半)。求满足条件的整数K的个数。
思路:
划分后两组数量相等,即提高组题目数=普及组题目数=N/2。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("hf.in","r",stdin);
freopen("hf.out","w",stdout);
int N;
cin>>N;
vector<int>d(N);
for(int i=0;i<N;i++){
cin>>d[i];
}
sort(d.begin(),d.end());
int f=N/2;
int k=d[f-1]+1;
int K=d[f];
if(k>K){
cout<<0<<endl;
}else{
cout<<K-k+1<<endl;
}
return 0;
}
T5 序列查询
题意:
给定一个初始为空的序列A,处理q个查询,每个查询是以下三种类型之一:将元素x插入序列A。在A中小于等于x的元素中,输出第k大的值(若不足k个则输出-1)。在A中大于等于x的元素中,输出第 k小的值(若不足k个则输出-1)。
思路:
由于需要高效处理插入和查询操作,选择平衡二叉搜索树(如multiset)来维护序列A。使用 upper_bound(x) 找到第一个大于x的元素位置。通过迭代器遍历小于等于x的元素,取第k个。使用lower_bound(x) 找到第一个大于等于x的元素位置。正向迭代遍历大于等于x的元素,取第k个。
代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("list.in","r",stdin);
freopen("list.out","w",stdout);
multiset<long long>s;
int q;
cin>>q;
while(q--){
long long p,x,k;
cin>>p>>x;
if(p==1){
s.insert(x);
}
else if(p==2){
cin>>k;
auto t=s.upper_bound(x);
bool g=true;
while(k-- && t!=s.begin())t--;
if(k>=0 || t==s.end())g=false;
cout<<(g?*t:-1)<<endl;
}
else{
cin>>k;
auto t=s.lower_bound(x) ;
while(--k && t!=s.end())t++;
if(t==s.end())cout<<-1<<endl;
else cout<<*t<<endl;
}
}
return 0;
}