A - Similar String
AC代码:
#include
#include
#include
using namespace std;
int main()
{
int n;
cin >> n;
string s, t;
cin >> s >> t;
bool flag = true;
for (int i = 0; i < n; i++) {
if (s[i] == t[i] || s[i] == '1' && t[i] == 'l' || s[i] == 'l' && t[i] == '1' || s[i] == '0' && t[i] == 'o' || s[i] == 'o' && t[i] == '0') continue;
else {
flag = false;
break;
}
}
if (flag) puts("Yes");
else puts("No");
return 0;
}
B - Discord
n个人
共m张照片,每张照片都是n个人排在一行,如果两个人没有挨在一起,他们就有可能感情不好,问可能有几对人感情不好
数据很小,直接模拟即可
AC代码:
#include
#include
#include
using namespace std;
const int N = 60;
bool e[N][N];
int a[N][N];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
cin >> a[i][j];
}
}
for (int i = 1; i <= m; i++) {
for (int j = 2; j <= n; j++) {
e[a[i][j - 1]][a[i][j]] = e[a[i][j]][a[i][j - 1]] = true;
}
}
int cnt = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (!e[i][j]&&i!=j) cnt++;
}
}
cout << cnt / 2 << endl;
return 0;
}
C - Dash
一个二维平面,小明一开始在原点(0,0)处,初始健康值为H,一共有M个物品可以获得健康值,它们的位置都已知
小明将会走N步,当前坐标为(x,y),消耗1健康值来走一步,根据Si来确定走的方向,
(x+1,y) if Si is R;
(x−1,y) if Si is L;
(x,y+1) if Si is U;
(x,y−1) if Si is D.
如果小明的健康值小于K,并且他所在的位置有物品,那么他的健康值变为K
如果他的健康值为负值,那么他就走不了了
问小明能否走完N步
感觉就是一个模拟题,但是数据比较大,如果用二维数组的话,会爆空间,想着能用哈希表压缩一下空间,使空间集中
但是没有得到满分,不知道哪里出了问题,可能是哈希冲突吧
代码如下:
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 99999997;
LL q[N];
//bool flag[N];
LL get_key(int x, int y) {
return x * 1000000001ll + y;
}
int find(int x,int y) {
LL key = get_key(x, y);
int t = (key % N + N) % N;
while (q[t] != -1 && q[t] != key) {
t++;
if (t == N) t = 0;
}
return t;
}
int main()
{
memset(q, -1, sizeof q);
int n, m, h, k;
cin >> n >> m >> h >> k;
string s;
cin >> s;
while(m--) {
int x, y;
cin >> x >> y;
int t = find(x, y);
if (q[t] == -1) q[t] = get_key(x, y);
}
int a = 0;
int b = 0;
for (int i = 0; i < n; i++) {
if (s[i] == 'R') a++;
else if (s[i] == 'L') a--;
else if (s[i] == 'U') b++;
else b--;
h--;
if (h < 0) {
puts("No");
return 0;
}
else {
int t = find(a, b);
//printf("a=%d,b=%d\n",a,b);
if (q[t] != -1 && h < k) {
//printf("key=%lld,t=%d,h=%d,k=%d\n", get_key(a,b),t, h,k);
h = k;
}
}
}
puts("Yes");
return 0;
}
然后正当我一筹莫展时
我通过看Virtual Standings,看到了一种我一看就懂的代码
纯模拟,不过不用数组,而是用set
AC代码:
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
set>st;
int n, m, h, k;
cin >> n >> m >> h >> k;
string s;
cin >> s;
while(m--) {
int x, y;
cin >> x >> y;
st.insert({x,y});
}
int a = 0;
int b = 0;
for (int i = 0; i < n; i++) {
if (s[i] == 'R') a++;
else if (s[i] == 'L') a--;
else if (s[i] == 'U') b++;
else b--;
h--;
if (h < 0) {
puts("No");
return 0;
}
if (h < k && st.count({ a,b })) {
h = k;
st.erase({ a,b });
}
}
puts("Yes");
return 0;
}
D - Shift vs. CapsLock
一共有三个按键,按每个键都要花费一定时间,问最少花多长时间能得到字符串S(由a和A组成),其中字符串S是事先给定的
花z毫秒来开关灯,起初灯是灭的
要想得到a,可以在灯灭的情况下花x毫秒,也可以在灯亮的情况下花y毫秒
要想得到A,可以在灯亮的情况下花x毫秒,也可以在灯灭的情况下花y毫秒
可以用动态规划,通过状态转移,用二维,第二维表示灯的状态,亮还是灭
其中z+min(x,y)的意思是从灯亮到灯灭得到a,可以先花z毫秒关灯,再花x毫秒得到a,也可以先花y毫秒得到a,再花z毫秒关灯,所以最少花费时间为z+min(x,y)
AC代码:
#include
#include
#include
#define int long long
using namespace std;
const int N = 3e5 + 10;
int f[N][2];
signed main()
{
int x, y, z;
cin >> x >> y >> z;
string s;
cin >> s;
int n = s.size();
//初始状态
if (s[0] == 'a') {
f[0][0] = x;
f[0][1] = z+min(x, y);
}
else {
f[0][0] = y;
f[0][1] = z+min(x, y);
}
for (int i = 1; i
代码修正:
#include
#include
#include
#include
#include
#define int long long
using namespace std;
const int N = 3e5 + 10;
int f[N][2];
signed main()
{
int x, y, z;
cin >> x >> y >> z;
string s;
cin >> s;
int n = s.size();
if (s[0] == 'a') {
f[0][0] = min(x, z + z + min(x, y));
f[0][1] = z + min(x, y);
}
else {
f[0][0] = min(y, z + z + min(x, y));
f[0][1] = z + min(x, y);
}
for (int i = 1; i < n; i++) {
if (s[i] == 'a') {
f[i][0] = min(f[i - 1][0] + x, f[i - 1][1] + z + min(x, y));
f[i][1] = min(f[i - 1][1] + y, f[i - 1][0] + z + min(x, y));
}
else {
f[i][0] = min(f[i - 1][0] + y, f[i - 1][1] + z + min(x, y));
f[i][1] = min(f[i - 1][1] + x, f[i - 1][0] + z + min(x, y));
}
}
cout << min(f[n - 1][0], f[n - 1][1]) << endl;
return 0;
}
E - A Gift From the Stars
参考叶梦璃愁
大致题意是有若干个star(star指的是一个顶点与其它k个点各连一条边,叫做level-k star),将所有star用一条边将叶子节点连成一个图(n个点,n-1条边),求每个star的点的个数
关键在于找到每个star的顶点,其中与叶子节点相连的点肯定是star的顶点,然后每个star的顶点相差3个倍数的边
AC代码:
#include
#include
#include
#include
#include
using namespace std;
const int N = 2e5 + 10;
int d[N];
bool st[N];
vector >e(N);
queue>q;
vectorans;
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n - 1;i++) {
int u, v;
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);//点u和点v连边
d[u]++, d[v]++;//度数加1
}
//找到一个度数为1的点,将与它相连的另一个点(即star的顶点)入队
for (int i = 1; i <= n; i++) {
if (d[i] == 1) {
q.push({ e[i][0],0 });
break;
}
}
//bfs,宽度优先搜索,利用队列
while (q.size()) {
auto t = q.front();
q.pop();
int u = t.first, dist = t.second;
int cnt = 0;//统计每个点的边数
//对于点u,统计它的边数
for (auto v : e[u]) {
if (!st[v]) q.push({ v, dist + 1 });
st[v] = true;
cnt++;
}
if (dist % 3 == 0) ans.push_back(cnt);
}//将答案放入vector容器中
sort(ans.begin(), ans.end());//将答案从小到大排序
for (auto x : ans) cout << x <<" ";
return 0;
}