Atcoder Beginner Contest 301 A~E

鼠鼠我又来了,这次知道D题思路,但是老是wa,同时有事也就没写完DE题,现在补了补

A - Overall Winner

给一个字符串s,包含了两个人比赛的结果,输出最终的结果

需要注意的是,如果两个人赢的场数一样,那么输出最先达到该场数的,这里拿一个标志表示一下

# include 
# define int long long
# define endl '\n'
# define x first
# define y second
# define INF 0x3f3f3f3f
# define pii pair<int, int>
# define uf(i, j, k) for (int i = j; i <= k; i ++)
# define df(i, j, k) for (int i = j; i >= k; i --)
# define mset(x, v) memset(x, v, sizeof x)

using namespace std;

void solve()
{
    int n;
    string s;
    cin >> n >> s;
    int a[2] {};
    int f = 0;
    for (auto c : s) 
    {
        if (c == 'T') 
        {
            a[0] ++;
            if (a[0] > a[1]) f = 0;
        }
        else 
        {
            a[1] ++;
            if (a[1] > a[0]) f = 1;
        }
    }
    if (a[0] > a[1]) cout << "T" << endl;
    else if (a[0] == a[1]) 
    {
        cout << (f == 0 ? "T" : "A") << endl;
    }
    else cout << "A" << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

B- Fill the Gaps

给一个序列,构造出相邻元素绝对值为1的新序列,模拟一下

# include 
# define int long long
# define endl '\n'
# define x first
# define y second
# define INF 0x3f3f3f3f
# define pii pair<int, int>
# define uf(i, j, k) for (int i = j; i <= k; i ++)
# define df(i, j, k) for (int i = j; i >= k; i --)
# define mset(x, v) memset(x, v, sizeof x)
/*
    @see 
*/
using namespace std;
const int N = 110;
int a[N];
void solve()
{
    int n;
    cin >> n;
    vector<int> ans;
    int t;
    cin >> t;
    ans.push_back(t);
    uf (i, 2, n) 
    {
        int x = ans[ans.size() - 1];
        cin >> t;
        if (abs(x - t) != 1) 
        {
            if (x > t) 
            {
                df (i, x - 1, t)
                {
                    ans.push_back(i);
                }
            }
            else if (x == t)
            {
                ans.push_back(t + 1);
                ans.push_back(x);
            }
            else
            {
                uf (i, x + 1, t)
                {
                    ans.push_back(i);
                }
            }
        } else ans.push_back(t);
    }
    for (auto x : ans) cout << x << " ";
} 

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

C-AtCoder Cards

给两个长度相等的字符串a和b,判断两个字符串是否通过替换@字符和重新排列后能够相等

  • 记录两个字符串 @ 的个数,记录字符串a的字符个数(哈希)
  • 遍历字符串b,记录b中不在字符串a的字符
  • 最后a哈希中的剩余字符就用b中的 @消除,b中剩余字符就用a中的@消除,判断能否相互消除
# include 
# define int long long
# define endl '\n'
# define x first
# define y second
# define INF 0x3f3f3f3f
# define pii pair<int, int>
# define uf(i, j, k) for (int i = j; i <= k; i ++)
# define df(i, j, k) for (int i = j; i >= k; i --)
# define mset(x, v) memset(x, v, sizeof x)
/*
    @see 
*/
using namespace std;


bool check(char ch) 
{
    if (ch == 'a' || ch == 't' || ch == 'c' || ch == 'o' || ch == 'd' || ch == 'e' || ch == 'r')
        return true;
    return false;
}
void solve()
{
    string a, b;
    cin >> a >> b;
    bool ok = true;
    int mp[26] {};
    int acnt = 0, bcnt = 0;
    for (auto c : a) 
    {
        if (c == '@') acnt ++;
        mp[c - 'a'] ++;
    }
    vector<char> bt;
    for (auto c : b) 
    {
        if (c == '@') bcnt ++;
        else 
        {
            if (mp[c - 'a'] > 0) mp[c - 'a'] --;
            else bt.push_back(c);        
        }
    }
    uf (i, 0, 25)
    {
        if (mp[i] > 0) 
        {
            if (check(i + 'a')) bcnt -= mp[i];
            else ok = false;
        }
    }
    for (auto x : bt)
    {
        if (check(x)) acnt -= 1;
        else ok = false;
    }
    ok = bcnt >= 0 && bcnt == acnt;
    cout << (ok ? "Yes" : "No") << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

D - Bitmask

给一个包含1 0 ?的字符串s和一个整数n,?可以替换成 1 或者 0 ,求出替换后 ≤ n \le n n 的最大值,如果没有输出-1

  • 先求出已有的 01 的最小值,即 ? 全部替换成 0 的值,这个值如果 > n > n >n,那么任何一个?替换成 1 都不能比 n n n
  • 然后逐位枚举?, 判断这个替换成 1 后的值会不会超过n,如果不会则将其替换
  • 最终的答案就是题目要求的最大值

这里使用位运算需要注意 溢出, 还有 pow 也是会溢出!!!鼠鼠我就是因为这个一直wa,以为自己开了long long万事大吉

# include 
# define int long long
# define endl '\n'
# define x first
# define y second
# define INF 0x3f3f3f3f
# define pii pair<int, int>
# define uf(i, j, k) for (int i = j; i <= k; i ++)
# define df(i, j, k) for (int i = j; i >= k; i --)
# define mset(x, v) memset(x, v, sizeof x)

using namespace std;
int n;
string s;

void solve()
{
    cin >> s >> n;
    int t = 0, m = s.length();
    int l = -1, r = m;
    while (++ l < -- r) swap(s[l], s[r]);
    auto get = [](int x) 
    {
        int ans = 1;
        while (x --) ans *= 2;
        return ans;
    };
    uf (i, 0, m - 1) if (s[i] == '1') t += get(i);
    if (t > n) t = -1;
    else 
    {
        df (i, m - 1, 0) 
        {
            // cout << t << " ";
            if (s[i] == '?' && (t + get(i)) <= n) t += get(i);
        }
    }
    cout << t << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

E - Pac-Takahashi

问题简述:

  • 给一个 H ∗ W H*W HW 网格,起初在起点S,要抵达终点G,最多走 T 步,要求在抵达终点的过程中尽可能多拿糖果 o,如果能抵达则输出最大糖果数,如果不能则输出-1

思路:

  • 近似旅行家问题,从起点到终点,每个糖果看做一个顶点,中间通过糖果的顺序和数目不确定,我们可以用二进制枚举出通过糖果的个数(糖果个数最多只有18个),最后取能够到达终点的最大值即可

  • 状态表示:dp[i][j] 从起点开始,经过状态i后, 抵达第 j 个糖果 的最短距离(状态i 为经过的糖果)

  • 状态转移:
    在这里插入图片描述

(吐槽一下csdn的markdown,渲染不出来公式)

  • 我们先处理出每个糖果到其他点的最短距离(BFS)
  • 然后类似旅行商的DP处理出从起点开始到其他糖果的最短距离
# include 
# define int long long
# define endl '\n'
# define x first
# define y second
# define INF 0x3f3f3f3f
# define pii pair<int, int>
# define vi vector<int>
# define vii vector<vi>
# define uf(i, j, k) for (int i = j; i <= k; i ++)
# define df(i, j, k) for (int i = j; i >= k; i --)
# define mset(x, v) memset(x, v, sizeof x)

using namespace std;
const int N = 310;
char g[N][N];
bool st[N][N];
int n, m, t;
int bx, by, ex, ey;
vector<pii> candy;
int d[] {0, 1, 0, -1, 0};

bool chmin(int &a, int b)
{
    if (a > b) 
    {
        a = b;
        return true;
    }
    else return false;
}

//枚举(tx, ty)这个点到其他点的最短距离
vii bfs(int tx, int ty)
{
    mset(st, false);
    vii res(N, vi(N, INF));
    res[tx][ty] = 0;
    queue<pii> q;
    q.push({tx, ty});
    while (q.size())
    {
        auto cur = q.front(); q.pop();
        int x = cur.x, y = cur.y;
        if (st[x][y]) continue;
        st[x][y] = true;
        uf (i, 0, 3) 
        {
            int dx = x + d[i], dy = y + d[i + 1];
            if (dx < 1 || dx > n || dy < 1 || dy > m || g[dx][dy] == '#' || st[dx][dy]) continue;
            if (chmin(res[dx][dy], res[x][y] + 1)) q.push({dx, dy}); 
        } 
    }
    return res;
}

void solve()
{
    cin >> n >> m >> t;
    uf (i, 1, n) 
    {
        cin >> g[i] + 1;
        uf (j, 1, m) 
        {
            if (g[i][j] == 'S') bx = i, by = j;
            if (g[i][j] == 'G') ex = i, ey = j;
            if (g[i][j] == 'o') candy.push_back({i, j});
        }
    }
    int cnt = candy.size();
    vector<vii> dist(cnt);
    uf (i, 0, cnt - 1) dist[i] = bfs(candy[i].x, candy[i].y); //处理每个糖果到每个点的最短路径

    vii dp(1 << cnt, vi(cnt, INF));
    uf (i, 0, cnt - 1) dp[1 << i][i] = dist[i][bx][by]; //初始化每个糖果到起点的路径,结合状态表示
    int all = 1 << cnt;
    uf (i, 1, all - 1)
    {
        uf (j, 0, cnt - 1)
        {
            if (dp[i][j] == INF) continue; //无法抵达j
            uf (k, 0, cnt - 1)
            {
                if ((i >> k) & 1) continue; //k不在状态i里面,可以作为下一个目标
                chmin(dp[i |(1 << k)][k], dp[i][j] + dist[j][candy[k].x][candy[k].y]);
            }            
        }
    }
    int ans = -1;
    vii none = bfs(bx, by); //先判断从起点直接走能不能抵达终点
    if (none[ex][ey] <= t) ans = 0;

    uf (i, 1, all - 1)
    {
        uf (j, 0, cnt - 1)
        {
            if (dp[i][j] + dist[j][ex][ey] <= t)
             //从起点开始,经过集合i中(拿了i情况的糖果),最后在第j个糖果的最短距离 + 第j个糖果到终点的距离
            {
                int cur = 0;
                uf (k, 0, cnt - 1) if (i >> k & 1) cur ++; //统计i情况中拿了多少糖果
                ans = max(ans, cur);
            }
        }
    }
    cout << ans << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    // cin >> t;
    while (t --) solve();
    return 0;
}

毕竟我们只有一生这么长
要用力给人间留下些印象

你可能感兴趣的:(Atcoder,c++,算法)