2024-3-10 学校比赛记录

T1 地铁

标签

图论

最短路

题目大意

有很多个地铁站,现在给定哪些地铁站是相连的。

我们定义任意两个地铁站之间都可以走过去,只有相连的地铁站才可以乘坐地铁。

求从 A 到 B 的最短路径。

思路

由于数据很水,所以普通的 Floyd 就可以过了。

我们先建边。

第一步:把所有地铁站两两相连,权值为距离除以步行的速度。

第二步:把所有联通的地铁站都建上一条权值为距离除以地铁速度的边。

第三步:如果 A 或 B 不是地铁站,令 A 和 B 与其他点建边。

第四步:求最短路,输出

赛事情况

用时 $1$ 小时。

代码长度 $188$ 行。

代码

#include <bits/stdc++.h>
using namespace std;
double vw, vs;//vw = Vwalk,vs = Vsubway
int n;
typedef pair <double, double> pdd;
#define mkp make_pair
vector <int> e[1005];
vector <double> v[1005];
pdd a[201];
map <pdd, int> mp;
double dis[205];
int vis[205];
double mmp[205][205];

double di(double x_, double y_, double x__, double y__) {
    return sqrt(abs(x_ - x__) * abs(x_ - x__) + abs(y_ - y__) * abs(y_ - y__));
}

void addedge(int x, int y, double z) {
    e[x].push_back(y);
    e[y].push_back(x);
    v[x].push_back(z);
    v[y].push_back(z);
    mmp[x][y] = mmp[y][x] = z;
}

struct node {
    int d, p;
    const bool operator <(const node &x) const {
        return x.d < d;
    }
};
priority_queue <node> q;

int main() {
    cin >> vw >> vs;
    cin >> n;

    for (int i = 0; i <= n + 1; i ++) {
        for (int j = 0; j <= n + 1; j ++) {
            mmp[i][j] = 0x7fffffff;
        }
    }

    for (int i = 1; i <= n; i ++) {
        cin >> a[i].first >> a[i].second;
        mp[a[i]] = i;
        dis[i] = 0x7fffffff;
        mmp[i][i] = 0;
    }

    mmp[0][0] = mmp[n + 1][n + 1] = 0;

    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j < i; j ++) {
            int x = i, y = j;
            e[x].push_back(y);
            e[y].push_back(x);
            double z = di(a[x].first, a[x].second, a[y].first, a[y].second) / vw;
            v[x].push_back(z);
            v[y].push_back(z);
            mmp[x][y] = mmp[y][x] = z;
        }
    }

    int x, y;

    while (cin >> x >> y && x != 0 && y != 0) {
        e[x].push_back(y);
        e[y].push_back(x);
        double z = di(a[x].first, a[x].second, a[y].first, a[y].second) / vs;
        v[x].push_back(z);
        v[y].push_back(z);
        mmp[x][y] = mmp[y][x] = z;
    }

    pdd A, B;
    cin >> A.first >> A.second >> B.first >> B.second;

    if (mp[A] == 0) {
        a[0] = A;
        mp[A] = 0;

        for (int i = 1; i <= n; i ++) {
            addedge(0, i, di(a[0].first, a[0].second, a[i].first, a[i].second) / vw);
        }
    }

    if (mp[B] == 0) {
        a[n + 1] = B;
        mp[B] = n + 1;

        for (int i = 1; i <= n; i ++) {
            addedge(n + 1, i, di(a[n + 1].first, a[n + 1].second, a[i].first, a[i].second) / vw);
        }
    }
    for (int k = 0; k <= n + 1; k ++) {
        for (int i = 0; i <= n + 1; i ++) {
            for (int j = 0; j <= n + 1; j ++) {
                mmp[i][j] = min(mmp[i][j], mmp[i][k] + mmp[k][j]);
            }
        }
    }
    printf("%.7lf", mmp[mp[A]][mp[B]]);
}

T2 硬币

标签

DP

思路

一眼 DP。

我们定义 dp[i][j] 为前重量总和为 $i$,价值总和为 $j$。

状态转移方程式就是:

dp[i][j] |=a[i - wei[i]][j - val[i]]

代码

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

struct str {
    int w, v;
} a[1005];
int n, W, tot, cnt;
int dp[105][10005];
#define V 10005

int main() {
    cin >> W >> n;

    for (int i = 1; i <= n; i ++) {
        int mi, ma, v;
        cin >> v >> mi >> ma;

        for (int j = mi; j <= ma; j ++) {
            a[++cnt].v = v;
            a[cnt].w = j;
        }
    }

    dp[0][0] = 1;

    for (int i = 1; i <= cnt; i ++) {
        for (int j = a[i].w; j <= W; j ++) {
            for (int k = a[i].v; k <= V; k ++) {
                dp[j][k] |= dp[j - a[i].w][k - a[i].v];
            }
        }
    }

    int ans = 0;

    for (int i = 1; i <= V; i ++) {
        if (dp[W][i])
            ans ++;
    }

    cout << ans;
}

T3 旗帜

标签

数学

题意

给定 $n$ 个黄色旗子和 $n$ 个红色旗子排成一排,我们定义如果两个左右挨着的旗子的颜色不同,那么不同度加一。

给定 $n$ 和 $m$,求 $n$ 个黄色旗子和 $n$ 个红旗子排成一列且不同度为 $m$ 的情况下,符合要求的拜访方式有几种。

思路

典型的数学题。

我们可以用 插板法 来推出公式。

公式:
$$
f(n, m) = A_2^2 \times C_{n – 1}^{\frac{m+1}{2}-1} \times C_{n – 1}^{\frac{m+2}{2}-1}
$$
我们直到 $C_a^b$ 的定义就是从 $a$ 里面无序的选取 $b$ 个的排列组合数量。

所以我们可以发现第一种颜色可以被分成 $\frac{m+1}{2}$ 段,第二种颜色可以被分成 $\frac{m+2}{2}$ 段。

而且每种颜色可以交换。

所以就得到这个公式了。

代码

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

int C(int a, int b) {
    //C^a_b
    long long ans = 1;

    for (int i = b; i >= b - a + 1; i --) {
        ans *= i;
    }

    for (int i = 1; i <= a; i ++) {
        ans /= i;
    }

    return ans;
}

signed main() {
    int n, m;
    cin >> n >> m;

    if (m == 1) {
        cout << 2;
        return 0;
    }

    cout << C((m + 2) / 2 - 1, n - 1) * 2ll * C((m + 1) / 2 - 1, n - 1);
}

T4 序列还原

题目

  给定一棵N个结点的树(即无环连通图)(2<=N<=10000)。所有点编号1到N。我们按照如下顺序打印一个序列:

1、取编号最小的叶子结点(即只连有一条边的点)。
2、打印这个结点的父结点的编号。
3、把这个结点连同他所连的边从树中删去(父结点保留)。
4、重复以上步骤,直到剩下一个点。(显然最后剩下的点编号为N。)

  按照这样的顺序,我们打印出了N-1个数。
  给定打印出的序列,请你还原出原来的树。

思路

运用拓扑排序。

自己看代码吧。

代码

#include <bits/stdc++.h>
using namespace std;
int a[10005], n, cnt[10005];
vector <int> e[10005];

int main() {
    int x;
//  cin >> x;

    while (cin >> x) {
        a[++n] = x;
        cnt[x] ++;
    }

    for (int i = 1; i <= n; i ++) {
        int flag;

        for (int j = 1; j <= n + 1; j ++) {
            if (a[i] == j)
                continue;

            if (cnt[j] == 0) {
                flag = j;
                break;
            }
        }

        cnt[flag] --;
        cnt[a[i]] --;
        e[flag].push_back(a[i]);
        e[a[i]].push_back(flag);
    }

    for (int i = 1; i <= n + 1; i ++) {
        sort(e[i].begin(), e[i].end());
        cout << i << ": ";

        for (int j = 0; j < e[i].size(); j ++) {
            cout << e[i][j] << " ";
        }

        cout << "\n";
    }
}
本文链接:https://ztrztr.top/archives/325
版权声明:本文 《2024-3-10 学校比赛记录》 为 ztrztr 原创。著作权归作者所有。
转载说明:联系作者或者评论区留言获得转载授权,并注明转载地址。

评论

  1. zhang_kevin
    Windows Chrome 116.0.0.0
    北京市 鹏博士BGP
    6 月前
    2024-3-11 19:57:38

    呵呵 我比你高60分

  2. endline_n
    Windows Chrome 122.0.0.0
    上海市 电信
    6 月前
    2024-3-14 22:38:42

    像我这种人的学校校赛都没有QAQ

    • Avatar photo
      博主
      endline_n
      Windows Edge 115.0.1901.203
      北京市 鹏博士/BGP
      6 月前
      2024-3-23 13:29:04

      😂

  3. Echo
    Macintosh Chrome 123.0.0.0
    江苏省徐州市 电信
    6 月前
    2024-3-23 15:27:14

    厉害

    • Avatar photo
      博主
      Echo
      iPad AppleWebKit 605.1.15
      北京市 鹏博士/BGP
      6 月前
      2024-3-31 21:24:01

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇