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)适合用在稠密图

  1. dist 置成正无穷,令第一个点的距离为 0
  2. 遍历所有点,找一条最短的路
  3. 更新邻点到当前点的最短距离
点击查看代码
 #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),可以求有边数限制的最短路,可以处理负权

  1. 把 dist 置成正无穷,起点距离为 0,循环 k 次(k 为边数限制),做 k 次松弛操作
  2. 每次备份,用上一次的结果来更新,避免被当前最短路更新
点击查看代码
 #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;
}
posted @ 2025-07-07 14:44  ha000star  阅读(75)  评论(0)    收藏  举报