2025暑期摸底赛(普及组)题解
大象喝水
https://www.luogu.com.cn/problem/B2029?contestId=256076
简单的模拟题,注意单位转换
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define pi 3.14
void solve()
{
int h,r,a;
cin>>h>>r;
a=20000/(pi*r*r*h)+1;
cout<<a;
}
int main()
{
int T=1;
//cin>>T;
while(T--)
{
solve();
}
return 0;
}
生日
https://www.luogu.com.cn/problem/P1104?contestId=256076
字符串,排序,结构体
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N=110;
struct ppp
{
string name;
int y,m,d;
int id;
}arr[N];
bool cmp(ppp A,ppp B)
{
if(A.y==B.y)
{
if(A.m==B.m)
{
if(A.d==B.d)
{
return A.id>B.id;
}
return A.d<B.d;
}
return A.m<B.m;
}
return A.y<B.y;
}
void solve()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>arr[i].name;
cin>>arr[i].y>>arr[i].m>>arr[i].d;
arr[i].id=i;
}
sort(arr+1,arr+1+n,cmp);
for(int i=1;i<=n;i++)cout<<arr[i].name<<'\n';
}
int main()
{
int T=1;
//cin>>T;
while(T--)
{
solve();
}
return 0;
}
全排列问题
https://www.luogu.com.cn/problem/P1706?contestId=255670
非常简单的dfs问题,梦开始的地方,当然c++中有内置的全排列函数,不过还是建议手搓吧
点击查看代码
#include <iostream>
using namespace std;
const int MAXN = 10; // 最大元素数量
int arr[MAXN]; // 存储待排列的元素
int path[MAXN]; // 存储当前路径(排列)
bool used[MAXN]; // 标记元素是否已被使用
int n; // 元素数量
// 深度优先搜索生成全排列
void dfs(int depth) {
if (depth == n) { // 到达叶子节点,输出当前排列
for (int i = 0; i < n; i++) {
printf("%5d",path[i]);
}
cout << endl;
return;
}
for (int i = 0; i < n; i++) {
if (!used[i]) { // 如果元素i未被使用
path[depth] = arr[i]; // 选择元素i加入路径
used[i] = true; // 标记元素i已被使用
dfs(depth + 1); // 递归搜索下一层
used[i] = false; // 回溯:撤销选择
}
}
}
int main() {
// 初始化待排列的元素
cin >> n;
for(int i = 0; i < n; i++)arr[i]=i+1;
// 初始化标记数组
for (int i = 0; i < n; i++) {
used[i] = false;
}
//用memset也可以
// 从深度0开始DFS
dfs(0);
return 0;
}
凌乱的yyy / 线段覆盖
https://www.luogu.com.cn/problem/P1803?contestId=255670
模拟,贪心,简单的区间合并
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
pair<int,int> a[N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].first>>a[i].second;
}
int ans=0;
int wei=0;
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
{
if(a[i].first>=wei)
{
ans++;
wei=a[i].second;
}
else
{
wei=min(a[i].second,wei);
}
}
cout<<ans;
return 0;
}
[NOIP 2005 普及组] 采药
https://www.luogu.com.cn/problem/P1048?contestId=255670
背包问题,动态规划dp,01背包
没接触过的同学或者不熟悉的同学可以看看大佬这篇背包九讲
https://www.cnblogs.com/jbelial/articles/2116074.html
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int m,n,t;
int dp[1050][1050];
int uset[105],price[105];
int main(){
cin>>t>>m;
for(int i=1;i<=m;i++)
cin>>uset[i]>>price[i];
for(int i=1;i<=m;i++)
for(int j=0;j<=t;j++){
if(j>=uset[i])
dp[i][j]=max(dp[i-1][j],dp[i-1][j-uset[i]]+price[i]);
else
dp[i][j]=dp[i-1][j];
}
cout<<dp[m][t];
return 0;
}
约瑟夫问题
https://www.luogu.com.cn/problem/P1996?contestId=255670
模拟,队列
点击查看代码
#include<bits/stdc++.h>
using namespace std;
queue<int> qu;
int main()
{
int b,c,idx=1;
cin>>b>>c;
for(int i=1;i<=b;i++)
{
qu.push(i);//模拟队列
}
while(!qu.empty())
{
if(idx==c)//如果这个人正好被踢
{
cout<<qu.front()<<" ";//先输出
qu.pop();//再删除
idx=1;//再从1开始报数
}
else if(idx!=c)//如果不被剔除
{
idx++;//报的数+1
qu.push(qu.front());//先把head压进队尾
qu.pop();//再把head删除
}
}
return 0;
}
【模板】单源最短路径(标准版)
https://www.luogu.com.cn/problem/P4779?contestId=255670
模板:
图论,最短路
Dijkstra: 单源最短路
时间复杂度O(n^2+m)适合用在稠密图
- dist 置成正无穷,令第一个点的距离为 0
- 遍历所有点,找一条最短的路
- 更新邻点到当前点的最短距离
点击查看代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 510;
const int INF = 0x3f3f3f3f;
int n, m;
int g[N][N], dist[N];
bool st[N];
int dijkstra() {
memset(dist, INF, sizeof dist);
dist[1] = 0;
for (int i = 1; i <= n; i++) {
int t = -1;
for (int j = 1; j <= n; j++)
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
st[t] = true;
for (int j = 1; j <= n; j++)
dist[j] = min(dist[j], dist[t] + g[t][j]); //更新当前节点到其他点的距离
}
if (dist[n] == INF) return -1;
else return dist[n];
}
int main() {
memset(g, INF, sizeof g);
cin >> n >> m;
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
g[u][v] = min(g[u][v], w); //稠密图用邻接矩阵存储
}
int ans = dijkstra();
cout << ans;
return 0;
}
dijkstra(堆优化)
时间复杂度: O(mlogn),用于稀疏图
1.使用优先队列(小根堆)
2.把 dist 置成正无穷,起点距离为 0,把起点放入堆中
3.每次用堆顶来更新距离
点击查看代码
#include <bits/stdc++.h>
#define PII pair<int,int>
using namespace std;
const int N=150010;
const int M=150010;
const int INF=0x3f3f3f3f;
int n,m;
int h[N],to[M],ne[M],w[M];
int idx;
int dist[N];
bool st[N];
void add(int a,int b,int c)
{
to[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int dijkstra()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0;
priority_queue<PII,vector<PII>,greater<PII>> heap;
heap.push({0,1});
while(heap.size())
{
PII k=heap.top();
heap.pop();
int ver=k.second,distance=k.first;
if(st[ver])continue;
st[ver]=true;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=to[i];
if(dist[j]>distance+w[i])
{
dist[j]=distance+w[i];
heap.push({dist[j],j});
}
}
}
if(dist[n]==INF)return -1;
else return dist[n];
}
int main()
{
memset(h,-1,sizeof h);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
cout<<dijkstra();
return 0;
}
Bellman - Ford 单源最短路有负权边
时间复杂度: O(nm),可以求有边数限制的最短路,可以处理负权
- 把 dist 置成正无穷,起点距离为 0,循环 k 次(k 为边数限制),做 k 次松弛操作
- 每次备份,用上一次的结果来更新,避免被当前最短路更新
点击查看代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 510, M = 10010;
struct Edge { int u, v, w; }edge[M];
int dist[N], backup[N], n, m, k;
bool st[N];
int bellman_ford() {
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for (int i = 1; i <= k; i++) {
memcpy(backup, dist, sizeof dist);
for (int j = 0; j < m; j++) {
Edge a = edge[j];
dist[a.v] = min(dist[a.v], backup[a.u] + a.w);
}
}
return dist[n];
}
int main() {
cin >> n >> m >> k;
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
edge[i] = { a,b,c };
}
int ans = bellman_ford();
if (ans > 0x3f3f3f3f / 2) cout << "impossible"; //一个数加上负数会比原来小,所以大于一个很大的数就认为无法到达
else cout << ans;
return 0;
}
以上是本类题可用的模板,以下是正解
点击查看代码
#include <bits/stdc++.h>
#define PII pair<int,int>
#define int long long
using namespace std;
const int N=3e5+10;
int h[N],to[2*N],ne[2*N],w[2*N],idx;
void add(int a,int b,int c)
{
to[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
bool st[N];
int dist[N];
void dijkstra(int x)
{
memset(dist,0x3f,sizeof dist);
dist[x]=0;
priority_queue<PII,vector<PII>,greater<PII>>heap;
heap.push({0,x});
while(heap.size())
{
PII tmp=heap.top();
heap.pop();
int ver=tmp.second;
int d=tmp.first;
if(st[ver])continue;
st[ver]=true;
for(int i=h[ver];~i;i=ne[i])
{
int j=to[i];
if(!st[j]&&d+w[i]<dist[j])
{
dist[j]=d+w[i];
heap.push({dist[j],j});
}
}
}
}
signed main()
{
memset(h,-1,sizeof h);
int n,m,s;
cin>>n>>m>>s;
while(m--)
{
int l,r,c;
cin>>l>>r>>c;
add(l,r,c);
}
dijkstra(s);
for(int i=1;i<=n;i++)cout<<dist[i]<<" ";
return 0;
}
[蓝桥杯 2025 国 B] 数字轮盘
https://www.luogu.com.cn/problem/P12832
数论,打表,找规律
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int t,n,k;
int main(){
cin>>t;
while(t--){
cin>>n>>k;
int x=(n-k%n)%n;
if(x%2==0)cout<<x/2<<'\n';
else if((x+n)%2==0)cout<<(x+n)/2<<'\n';
else cout<<"-1\n";
}
return 0;
}
[SDOI2006] 保安站岗
https://www.luogu.com.cn/problem/P2458?contestId=255670
树形dp
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N=2e4;
vector<int> son[N];
int k[N];
int f[N][3];
bool du[N];
void dfs(int u,int fa)
{
int t=0;
f[u][0]=k[u];
for(int i=0;i<son[u].size();i++)
{
int v=son[u][i];
if(v==fa)continue;
dfs(v,u);
f[u][0]+=min(f[v][0],min(f[v][1],f[v][2]));
f[u][2]+=min(f[v][0],f[v][1]);
if(f[t][0]-min(f[t][0],f[t][1])>f[v][0]-min(f[v][0],f[v][1])) t=v;
}
f[u][1]=f[t][0];
for(int i=0;i<son[u].size();i++)
{
int v=son[u][i];
if(v==fa||v==t)continue;
f[u][1]+=min(f[v][0],f[v][1]);
}
}
int main()
{
int n;
cin>>n;
for(int i=1,id,m;i<=n;i++)
{
cin>>id;
cin>>k[id];
cin>>m;
while(m--)
{
int q;
cin>>q;
son[id].push_back(q);
du[q]=true;
}
}
int root;
for(int i=1;i<=n;i++)
{
if(!du[i])
{
root=i;
break;
}
}
f[0][0]=1e9;
dfs(root,0);
cout<<min(f[root][0],f[root][1]);
return 0;
}

浙公网安备 33010602011771号