Loading

AtCoder Beginner Contest 257 A - F

传送门

vp 了一场之前的 ABC,不知道是水平下降还是真的难,就很多要想很久,寄了

A - A to Z String 2

向下取整考虑一下是在哪个组就好

#include <iostream>
using namespace std;

int main()
{
    int n, x;
    cin >> n >> x;
    x--;
    x /= n;
    cout << (char)('A' + x) << endl;
    return 0;
}

B - 1D Pawn

模拟

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e4 + 10;
int num[maxn], vis[maxn];

int main()
{
    int n, k, q;
    cin >> n >> k >> q;
    for(int i=1; i<=k; i++)
    {
        cin >> num[i];
        vis[num[i]] = i;
    }
    while(q--)
    {
        int x;
        cin >> x;
        vis[num[x]] = 0;
        if(num[x] < n && vis[num[x] + 1] == 0)
            num[x]++;
        vis[num[x]] = 1;
    }
    // sort(num + 1, num + k + 1);
    for(int i=1; i<=k; i++)
    {
        if(i != 1) cout << " ";
        cout << num[i];
    }
    cout << endl;
    return 0;
}

C - Robot Takahashi

考虑从小到大枚举所有可能的答案,因为从小到大,所以总共为找所有 \(f(x)\) 的代价也就是 \(O(n)\),每次 x 增加的时候,就从上一次的答案继续往下查找

我一开始以为相同重量的成年人和小孩没办法分辨,因此取了相邻重量的两个人的中间值作为枚举的答案,但是后来发现有点蠢了,直接枚举所有人的重量就可以了

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
#define pii pair<double, int>

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    string s;
    cin >> n >> s;
    vector<pii>a(n);
    vector<double>b;
    int ch = 0, ad = 0;
    for(int i=0; i<n; i++)
    {
        int x;
        cin >> x;
        a[i] = {x, s[i] - '0'};
        if(s[i] == '1') ad++;
    }
    sort(a.begin(), a.end());
    b.push_back(-1);
    for(int i=1; i<n; i++)
        b.push_back((a[i].first + a[i].first) / 2);
    b.push_back(1e9 + 10);
    
    int ans = ad, tp = 0;
    for(int i=0; i<b.size(); i++)
    {
        while(tp < n && a[tp].first < b[i])
        {
            if(a[tp].second == 1) ad--;
            else ad++;
            tp++;
        }
        ans = ad > ans ? ad : ans;
    }
    cout << ans << endl;
    return 0;
}

D - Jumping Takahashi 2

dijkstra 或 Floyd 或 二分

dijkstra 枚举从每个点出发到所有点的最大代价的最小值

同理,Floyd 跑完之后再找这个最小值

二分答案,通过 bfs 判断是否有个点能跑遍历所有的点

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
typedef long long ll;
#define pii pair<double, int>
const int maxn = 210;
const double eps = 1e-8;
ll gra[maxn][maxn];
int vis[maxn];

struct node
{
    ll x, y, val;
    node(){}
    node(ll _x, ll _y, ll _v){x = _x; y = _y; val = _v;}
    bool operator < (const node& a) const
    {
        return a.val < val;
    }
}num[maxn];

ll dis(node& a, node& b)
{
    return abs(a.x - b.x) + abs(a.y - b.y);
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    for(int i=1; i<=n; i++)
        cin >> num[i].x >> num[i].y >> num[i].val;

    for(int i=1; i<=n; i++)
    {
        for(int j=i+1; j<=n; j++)
        {
            ll s = dis(num[i], num[j]);
            gra[i][j] = (s + num[i].val - 1) / num[i].val;
            gra[j][i] = (s + num[j].val - 1) / num[j].val;
        }
    }
    ll ans = 1e17 + 10;
    for(int i=1; i<=n; i++)
    {
        for(int j=j=1; j<=n; j++) vis[j] = 0;
        priority_queue<node>q;
        q.push(node(i, i, 0));
        ll temp = 0;
        int cnt = n;
        while(q.size() && cnt)
        {
            node now = q.top();
            q.pop();
            if(vis[now.y]) continue;
            cnt--;
            vis[now.y] = 1;
            temp = max(temp, now.val);
            for(int j=1; j<=n; j++)
                if(vis[j] == 0)
                    q.push(node(now.y, j, gra[now.y][j]));
        }
        ans = min(ans, temp);
    }
    cout << ans << endl;
    return 0;
}

E - Addition and Multiplication 2

首先要选个代价最小的,且价值最高,保证数字足够长

然后剩下的前就考虑如何从高位给数字“升级”,也就是枚举能够到的价值最高的数字

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
pii num[20];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n;
    cin >> n;
    for(int i=0; i<9; i++)
    {
        int x;
        cin >> x;
        num[i] = {x, -(i + 1)};
    }
    sort(num, num + 9);
    for(int i=0; i<9; i++) num[i].second = -num[i].second;
    int cnt = n / num[0].first;
    int nn = n % num[0].first;
    if(cnt == 0) cout << 0;
    while(cnt && nn)
    {
        int way = num[0].second, ans = num[0].first + nn, x = 0;
        for(int i=1; i<9; i++)
        {
            if(num[i].first <= ans && num[i].second > way)
            {
                way = num[i].second;
                x = num[i].first;
            }
        }
        if(way == num[0].second) break;
        cout << way;
        nn = nn - x + num[0].first;
        cnt--;
    }
    while(cnt--) cout << num[0].second;
    cout << endl;
    
    return 0;
}

F - Teleporter Setting

bfs

先构建一个 0 号虚拟点,最后再遍历这个点是其他的点

答案有两种来源:

  1. 本身从 1 直接到达 n(可经过 0 号虚拟点)

  2. 经过 0 号虚拟点和当前假设的点 i 之间的代价为 0 的特殊边

对于第一种情况,只用计算最短路即可

对于第二种情况,则为 min(dis[1][0] + dis[i][n], dis[1][i] + dis[0][n])

综上,计算出 1 和 n 到其他所有点的最短路即可,然后枚举假设 0 号虚拟点为 i 号点,然后找最小的情况

我原本的写法比较笨,现在改用了上述这种写法

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <array>
#include <algorithm>
using namespace std;
const int maxn = 3e5 + 10;
const int inf = 1e8 + 10;
int n, m;
vector<int>gra[maxn];

vector<int> bfs(int s)
{
    queue<array<int, 2> >q;
    vector<int> dis(n + 1, inf);
    q.push({s, 0});
    while(q.size())
    {
        auto [x, d] = q.front();
        q.pop();
        if(dis[x] != inf) continue;
        dis[x] = d;
        for(auto i : gra[x])
            if(dis[i] == inf) q.push({i, d + 1});
    }
    return dis;
}

int main()
{
    cin >> n >> m;
    for(int i=0; i<m; i++)
    {
        int x, y;
        cin >> x >> y;
        gra[x].push_back(y);
        gra[y].push_back(x);
    }
    auto dis1 = bfs(1);
    auto disn = bfs(n);
    for(int i=1; i<=n; i++)
    {
        int ans = min({dis1[n], dis1[0] + disn[i], dis1[i] + disn[0]});
        if(ans == inf) ans = -1;
        if(i != 1) cout << " ";
        cout << ans;
    }
    cout << endl;
    return 0;
}
posted @ 2022-07-02 15:30  dgsvygd  阅读(59)  评论(0编辑  收藏  举报