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;
}
二进制解法tql
Orz