河南萌新联赛2025第(六)场:郑州大学补题
文章目录
- A.守护者之战
- E.数字支配
- I.外卖大战
- L.整数商店的购物之旅
- K.还在分糖果!
- D.穿过哈气之门
- J.凹包
- F.迷宫穿越
A.守护者之战
这题题意有点不太清楚,但是答案上应该就是直接判断当任意一个人(无论敌我)生命值降低到 0 以下时,他会立即引爆体内的能量核心。,是否成立,只要有一个1就成立
#include<bits/stdc++.h>
using namespace std;
#define IOS ios;;sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
#define endl '\n'
const int N=1e6+6;
int a[N];
int b[N];
signed main()
{int n,m;cin>>n>>m;int x=1;for(int i=1;i<=n;i++){cin>>a[i];if(a[i]==1){x=0;} }for(int i=1;i<=m;i++){cin>>b[i];}if(x){cout<<"NO";}else{cout<<"YES";}return 0;
}
E.数字支配
这题就是在1到n内找一个数字使其字典序等级最大,用字符串处理更加简单明了,如果用正常数组的话,可能容易写错
#include<bits/stdc++.h>
using namespace std;
#define IOS ios;;sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
#define endl '\n'
signed main()
{string s;cin>>s;if(s.size()==1){cout<<s;}else{bool vis=1;for(int i=0;i<s.size()-1;i++){if(s[i]!='9'){vis=0;break;}}if(vis){cout<<s;}else{for(int i=0;i<s.size()-1;i++){cout<<"9";}}}return 0;
}
I.外卖大战
这题就是根据题意模拟就行了
#include<bits/stdc++.h>
using namespace std;
#define IOS ios;;sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
#define endl '\n'
int a[1006];//用户
int b[4]={0};//平台优惠力度
int c[4]={0};//模拟第三个规则
int sl[4]={0};//订单数量
signed main()
{int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}for(int i=1;i<=n;i++){int x=INT_MIN;for(int j=1;j<=3;j++){if(b[j]>=a[i]){b[j]++;sl[j]++;c[j]=0;x=j;break;}}for(int j=1;j<=3;j++){if(j==x){x=INT_MIN;continue;}else{c[j]++;if(c[j]==3){b[j]+=2;c[j]=0;}}}}for(int i=1;i<=3;i++){cout<<sl[i]<<" ";}return 0;
}
L.整数商店的购物之旅
这题其实就是一个简单的二分答案求最大值的题,注意千万不要记错模板,多加1就可能进入死循环
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
#define endl '\n'
int a,b,c;
bool check(int mid)//将mid作为答案代入,看是否符合题意
{int x=mid;int y=0;while(x>0){x=x/10;y++;}int z;z=a*mid+b*y;if(z<=c){return true;}else{return false;}
}
signed main()
{cin>>a>>b>>c;int l=0;int r=1e9;int sum;while(l<r)//模板{int mid=(l+r+1)/2;if(check(mid)){l=mid;sum=l;}else{r=mid-1;}}cout<<sum;return 0;
}
K.还在分糖果!
由题意可知,每十个数中就会有一个被去掉,所以可以将n转化为九进制,但是转化后根据样例我们会发现,本来是9变成了8,本来是8变成了7,所以最后要稍作修改
#include<bits/stdc++.h>
using namespace std;
#define IOS ios;;sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
#define endl '\n'
signed main()
{int t;cin>>t;while(t--){int n;cin>>n;int a[15];int i=0;vector<int>ve;while(n>0)//进制转化过程{int x=n%9;if(x>=7){x++;}ve.push_back(x);n=n/9;}for(int i=ve.size()-1;i>=0;i--){cout<<ve[i];}cout<<endl;}return 0;
}
D.穿过哈气之门
这题题意很明显就是计算每一种包含全部种类元素的区间,对数组我们可以这样操作,遍历数组,每次只从i后面来寻找包含的数组,这样就不会导致所找到全部数组中有重复数组
#include<bits/stdc++.h>
using namespace std;
#define IOS ios;;sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
#define endl '\n'
const int N=1e5+6;
int a[N];
signed main()
{int n,m;cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];}map<int,int>mp;int l=1;//每次从l往后找int r=0;//记录包含全部种类元素区间的尾节点,那么后面有几个数就是有几种情况(包含区间本身)int c=0;//记录当前区间内元素种类数int sum=0;//记录总区间种类数while(r<n)//限制条件{while(r<n&&c<m)//限制条件{ r++;if(mp[a[r]]==0){c++;}mp[a[r]]++;}if(c==m)//一定要注意,如果上面遍历完后c不一定等于m{sum+=n-r+1;while(c==m){mp[a[l]]--;//l不断向右,所以之前经过的节点会出数组if(mp[a[l]]==0){c--;}l++;if(c!=m){break;} sum+=n-r+1;}}else{break;}}cout<<sum;return 0;
}
J.凹包
这个之前从来没接触过,也是涨知识了
- 凸包的定义:
凸包是包含所有原始点的最小凸多边形,其顶点一定是原始点的子集(凸包顶点只能从原始点中选择,不会凭空生成新点)。因此,凸包顶点数 ≤ 原始点数是必然结论(不可能出现 “凸包顶点数超过原始点数” 的情况,原代码中else
分支实际永远不会触发)。- 凸多边形 vs 凹多边形的本质区别:
- 若一个多边形是凸多边形:其所有顶点都在自身的凸包上(因为凸多边形的最小凸包就是它本身),此时 “凸包顶点数 = 原始点数”。
- 若一个多边形是凹多边形:其至少有一个顶点(或内部点)不在自身的凸包上(凹多边形的凸包会 “跳过” 凹陷处的顶点,用更外侧的顶点构成凸边界),此时 “凸包顶点数 < 原始点数”。
判断凹多边形:
1.只有当凸包顶点数 < 原始点数时,才存在点不在凸包上,进而说明是凹多边形。
#include<bits/stdc++.h>
using namespace std;
#define IOS ios;;sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
#define endl '\n'
const int N=2e5+6;
pii ve[N];//存储输入的点坐标
pii pa[N]; //存储凸包上的点
bool cmp(pii p,pii q)//对各个坐标排序
{if(p.fi==q.fi){return p.se<q.se;}return p.fi<q.fi;
}
int mc(int x1,int y1,int x2,int y2,int x3,int y3)//叉积计算
{return x1*y2+x3*y1+x2*y3-x3*y2-x2*y1-x1*y3;
//结果为正:逆时针方向
//结果为负:顺时针方向
//结果为 0:共线
}
signed main()
{int n;cin>>n;for(int i=1;i<=n;i++){cin>>ve[i].fi>>ve[i].se;}if(n==3)//特殊判断{cout<<"No";}else{ sort(ve+1,ve+n+1,cmp);int c=0;for(int i=1;i<=n;i++)//构建下凸包{// 当至少有2个点且新点导致凹形时,删除前一个点while(c>1&&mc(pa[c].fi,pa[c].se,pa[c-1].fi,pa[c-1].se,ve[i].fi,ve[i].se)>0){c--;}pa[++c]=ve[i];}int d=c;for(int i=n-1;i>=1;i--)//构建上凸包,这里的n-1是由于{// 当至少有下凸包+1个点且新点导致凹形时,删除前一个点while(c>d&&mc(pa[c].fi,pa[c].se,pa[c-1].fi,pa[c-1].se,ve[i].fi,ve[i].se)>0){c--;}pa[++c]=ve[i];}c--;//起始点会被计入两次if(c<=n){cout<<"YES";}else{cout<<"NO";} } return 0;
}
2.判断 “按已知顺序(如顺时针 / 逆时针)输入的多边形是否为凹多边形
如果发现任何一个顶点处的转向与其他顶点不一致(出现负的叉积),说明这是凹多边形
#include<bits/stdc++.h>
using namespace std;
#define IOS ios;;sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
#define endl '\n'
const int N=2e5+6;
pii a[N];
int mc(pii p1, pii p2, pii p3) {//计算叉积return (p2.fi - p1.fi) * (p3.se - p2.se) - (p2.se - p1.se) * (p3.fi - p2.fi);
}
signed main()
{int n;cin>>n;for(int i=0;i<n;i++){cin>>a[i].fi>>a[i].se;}if(n==3)//特殊判断{cout<<"No";}else{int vis=1;//标记作用for(int i=0;i<n;i++){pii p2=a[(i+1)%n];//取余n是为了最后两个会超出的情况,a[n]就相当于a[0],a[n+1]就相当于a[1]pii p3=a[(i+2)%n];if(mc(a[i],p2,p3)<0)//此时其就是一个凹多边形{cout<<"Yes";vis=0;break;}}if(vis){cout<<"No";}} return 0;
}
F.迷宫穿越
这题虽然题面与其说明不太一样,但是其实就是就从左上角走到右下角的最短路问题,比正常求最短路多了一个可以穿过障碍的条件,此时在写的时候一定要注意,每条路有可能会经过一个相同的点,所以此时要分别记录每个点的各种情况,此时就可以用到一个三维数组,来记录情况
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
#define endl '\n'
const int INF=0x3f3f3f3f;
char ch[1006][1006];//原数组
bool vis[1006][1006];//标记数组
int d[1006][1006][11];//表示到达(x,y)且剩余k次破坏能力时的最短距离
int dx[]={1,0,-1,0};//四个方向的偏移
int dy[]={0,1,0,-1};
priority_queue<pair<pii,pii>,vector<pair<pii,pii>>,greater<pair<pii,pii>>>pq;
//存储{ {距离, 剩余破坏次数}, {x坐标, y坐标} },由于本人之前写的是用pair二元组,这里可以改成结构体
signed main()
{int n,m,k;cin>>n>>m>>k;memset(vis,0,sizeof(vis));for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>ch[i][j];if(ch[i][j]=='#'){vis[i][j]=1;}}}memset(d,INF,sizeof(d));d[0][0][k]=0;pq.push({{0,k},{0,0}});bool bl=1;while(!pq.empty()){pair<pii,pii>x=pq.top();pq.pop();if(x.se.fi==n-1&&x.se.se==m-1)//表示到达目标点{bl=0;cout<<x.fi.fi;break;}for(int i=0;i<4;i++)//遍历四种方向情况{int x1=x.se.fi+dx[i];int y1=x.se.se+dy[i];if(x1>=0&&x1<n&&y1>=0&&y1<m)//表示没有越界{if(!vis[x1][y1])//不是障碍物{if(d[x1][y1][x.fi.se]>x.fi.fi+1)//比较最短路{d[x1][y1][x.fi.se]=x.fi.fi+1;pq.push({{x.fi.fi+1,x.fi.se},{x1,y1}});}}else//是障碍物{if(x.fi.se>0&&d[x1][y1][x.fi.se-1]>x.fi.fi+1)//此时判断是否还有瞬移卷轴与比较最短路//注意这里是d[x1][y1][x.fi.se-1],而不是d[x1][y1][x.fi.se]{d[x1][y1][x.fi.se-1]=x.fi.fi+1;pq.push({{x.fi.fi+1,x.fi.se-1},{x1,y1}});}}}}}if(bl){cout<<"-1";}return 0;
}
这题本人写的比较繁杂
如果有错误,烦请指出