A - Shampoo

Code

signed main()
{
    int v, a, b, c;
    cin >> v >> a >> b >> c;
        
    while (1)
    {
        if (v < a)  {puts("F"); return 0;}
        v -= a;
        
        if (v < b)  {puts("M"); return 0;}
        v -= b;

        if (v < c)  {puts("T"); return 0;}
        v -= c;
    }
}

B - Hit and Blow

Code

signed main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)	cin >> a[i];
    for (int i = 1; i <= n; i++)	cin >> b[i];
        
    int cnt1 = 0, cnt2 = 0;
    for (int i = 1; i <= n; i++)	
        if (a[i] == b[i])	cnt1++;
 	
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (a[i] == b[j])	cnt2++;
 		
    cout << cnt1 << endl << cnt2 - cnt1;
    return 0;
}

C - Collision 2(排序)

Code

struct Node
{
    int x, y, id;
    bool operator< (const Node &W)const 
    {
        if (y != W.y)   return y < W.y;  // 优先按y坐标从大到小排序
        return x < W.x; 
    }
}node[N];

void solve()
{
    int n;  cin >> n;
    for (int i = 1; i <= n; i++)    cin >> node[i].x >> node[i].y, node[i].id = i;
    string s;    cin >> s;

    sort(node + 1, node + n + 1);
    int direct = 0, last = -1;  // direct = 0,表示朝向左
    for (int i = 1; i <= n; i++)
    {
        if (last != node[i].y)   last = node[i].y, direct = 0;  // 切换到不同的y坐标后,x坐标最小的那个假定向左
        else
        {
            if (s[node[i].id - 1] == 'L' && direct == 1)
            {
                puts("Yes");
                return;
            }
        }
        if (s[node[i].id - 1] == 'R')   direct = 1;
    }

    puts("No");
}

D - Moves on Binary Tree(栈/二进制)

Code1 (栈解法)

void solve()
{
    long long n, x;	cin >> n >> x;
    string s;	cin >> s;
    
    vector<char> v;  // vector可以模拟栈
    for (int i = 0; i < n; i++)
    {   
        // 如果栈v不为空,并且当前字符是'U',栈中末尾是'L'或'U',两个操作可以抵消,所以直接去掉末尾
    	if (s[i] == 'U' && v.size() > 0 && (v.back() == 'L' || v.back() == 'R'))  
        	v.pop_back();
        else 
            v.push_back(s[i]);
    }
                
    for (auto now : v)
    {
        if (now == 'U') 	x /= 2;
        if (now == 'L') 	x *= 2;
        if (now == 'R')		x = 2 * x + 1;
    }
    cout << x;
}

Code2 (二进制解法)

#include <bits/stdc++.h>
using namespace std;
int main()
{
    long long n, x;	cin >> n >> x;
    string s, t;	cin >> s;

    t = bitset<99>(x).to_string();  // 将数字转换为二进制字符串
    for(auto c:s)
        if(c == 'U') t.pop_back();  // x除以2相当于右移一位,即去掉末位
        else t += c =='L'?'0':'1';  // x乘以2相当于末位加0, x乘以2+1相当于末位+1

    /*  
        将处理完的二进制字符串再转为long型 
        stol()是将字符串转换为十进制,第2个占位符是起始位置,第3个占位符是当前字符串的进制
    */
    cout << stol(t,0,2) <<endl;  }

E - Edge Deletion(最短路,Floyd)

题目描述

给定一个 $n(n \le 300)$ 个节点无向图,问最多可以删除多少条边,使得删除后的图,对于两个节点 $u, v$ 其最短路没有发生改变。

解题思路

补题之前看到了这篇文章, 把思路解释得很清晰,不再赘述
此处仅对文中所给代码做些注释

Code

void solve()
{
	memset(g, 0x3f, sizeof g);  // 由于下面输入时因为判断重边取较小值,所以这里初始化为0x3f
    int n, m;	cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int u, v, w;	cin >> u >> v >> w;
        g[u][v] = min(g[u][v], w);  // 判断重边取较小值
        g[v][u] = min(g[v][u], w);
    }
    
    for (int k = 1; k <= n; k++)  // floyd算法
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
    
    int retain = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
        {
            if (i == j)	continue;
            int flag = 1;  // 如果不是由k构成的最短边,肯定是可以删去的
            for (int k = 1; k <= n; k++)  
                if (k != i && k != j && g[i][j] == g[i][k] + g[k][j])	flag = 0;
            retain += flag;
        }
    
    // 这里retain / 2的原因是因为存储的无向边,被记录了两次
    cout << m - retain / 2 << endl;
}

上一篇 下一篇