第十二届蓝桥杯C++A组

B 直线

在这里插入图片描述

#include<iostream>
#include<vector>
#include<set>
#include<cmath>
#include<climits>

using namespace std;

struct Point{
    int x, y;
    Point(int a, int b):x(a),y(b){}
};

struct Line{
    double k, b;
    Line(double x, double y):k(x),b(y){}
//    Line& operator = (const Line& li){
//        if(abs(k - li.k) < 1e-6 && abs(b - li.b) < 1e-6)
//        return *this;
//    }
    friend bool operator<(const Line & x,const Line & y)
    {
        if(x.k < y.k)return true;
        if(abs(x.k - y.k) < 1e-6){
            return x.b < y.b;
        }
    }
};

int main()
{
    vector<Point> p;
    set<Line> kb;
    for(int i = 0; i < 20; i++){
        for(int j = 0; j < 21; j++){
            Point a(i, j);
            p.push_back(a);
        }
    }
    int l = p.size();
    for(int i = 0; i < l - 1; i++){
        for(int j = i + 1; j < l;j++){
            double k = 0, b = 0;
            if(p[i].x - p[j].x != 0 && p[i].y - p[j].y != 0){
                k = 1.0* (p[i].y - p[j].y) / (p[i].x - p[j].x);
                b = p[i].y - k * p[i].x;
            }
            else if(p[i].y - p[j].y == 0){
                k = 0;
                b = p[i].y;
            }
            else{
                k = INT_MAX;
                b = p[i].x;
            }
            Line li(k, b);
            //kb.insert(li);
            if(kb.count(li) == 0){
                kb.insert(li);
                //cout << "√" << endl;
            }
//            cout << "dian:" << p[i].x << ' ' << p[i].y << ' ';
//            cout << "dian:" << p[j].x << ' ' << p[j].y << endl;
//            cout << k << ' ' << b << endl << endl;
        }
    }
    cout << kb.size();
    return 0;
}

D 路径

在这里插入图片描述
答案:10266837

1.用了Dijkstra 算法,因为只求最短路径长度,下面的path数组可以不用

#include<iostream>
#include<climits>

using namespace std;

int g[2025][2025];  //图
bool f[2025];       //标记各顶点是否找到最短路径
int dist[2025];     //最短路径长度
int path[2025];     //路径上的前驱结点
int imax = INT_MAX;

int gcd(int a, int b){ //a >= b
    int c = b;
    while(a % b != 0){
        c = a % b; a = b; b = c;
    }
    return c;
}

int bei(int a, int b){ //a >= b
    int c = gcd(a, b);
    return a / c * b;
}

int main()
{
    //初始化图
    for(int i = 1; i <= 2021; ++i){
        g[i][i] = imax;
        for(int j = i + 1; j <= 2021; ++j){
            if(j - i <= 21){
                g[i][j] = bei(j, i); g[j][i] = g[i][j];
            }
            else{
                g[i][j] = imax; g[j][i] = imax;
            }
        }
    }
    //初始化功能数组
    f[1] = true; dist[1] = 0; path[1] = -1;
    for(int i = 2; i <= 2021; i++){
        f[i] = false; dist[i] = g[1][i]; path[i] = (g[1][i] == imax) ? -1 : 0;
    }

    int k = 2020;
    while(k){
        k--;
        //找到还没确定最短路径,且dist最小的点Vt,标记其为找到最小路径
        int mind = imax; int t;
        for(int i = 2; i <= 2021; i++){
            if(f[i] == false && dist[i] < mind){
                t = i;
                mind =dist[i];
            }
        }
        f[t] = true;
        //对于邻接自Vt的结点Vj,更新最短路径
        for(int j = 2; j <= 2021; j++){
            if(g[t][j] != imax && f[j] == false && dist[t] + g[t][j] < dist[j]){
                dist[j] = dist[t] + g[t][j];
                path[j] = t;
            }
        }
    }

    cout << dist[2021];

    return 0;
}

2.Bellon-Ford算法

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const int inf=0x3f3f3f3f;
const int maxn=1e5+5;
const int N=6e6+5;
const LL mod=998244353;
const double pi=acos(-1);

int gcd(int a,int b){
    if(b==0) return a;
    return gcd(b,a%b);
}
struct node{
    int u,v,w;
    node(int uu,int vv,int ww) { u=uu,v=vv,w=ww; }
};
int n,dis[maxn];
vector<node>g;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) dis[i]=inf; dis[1]=0;
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            if(j-i>21) continue;
            g.push_back( node(  i , j , i*j/gcd(i,j)  ) );
        }
    for(int i=1;i<=n-1;i++)
    {
        bool f=0;  //在某次循环不再进行松弛时,直接退出循环
        for(int j=0;j<g.size();j++)
        {
            int u=g[j].u,v=g[j].v,w=g[j].w;
            if(dis[v]>dis[u]+w)
                f=1,dis[v]=dis[u]+w;
        }
        if(f==0) break;
    }
    printf("%d\n",dis[n]);
    return 0;
}

H 左孩子右兄弟

在这里插入图片描述
在这里插入图片描述
思路:建树,深搜

#include<bits/stdc++.h>
using namespace std;

//dfs,每次都取底层最大的,把这一层的每一个子结点都放最后取最大值+下面一层的层数

vector<int> node[100005];  //储存i的子结点
int high[100005];
int ans;

void dfs(){
    stack<int> st;
    st.push(1);
    while(!st.empty()){
        int top = st.top();
        st.pop();
        int len = node[top].size();
        for(int i = 0; i < len; i++){
            int child = node[top][i];
            st.push(child);
            high[child] = high[top] + len; //把每一个子结点放最后
            ans = max(ans, high[child]);
        }
    }

}

int main()
{
    int n, fa;
    cin >> n;
    for(int i = 2; i <= n; i++){
        cin >> fa;
        node[fa].push_back(i);
    }
    dfs();  //注意根节点高度为0
    cout << ans;
    return 0;
}

参考:https://blog.csdn.net/qq_45856614/article/details/115827861

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值