Atcoder beginner contest 303

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步

感觉就是一个模拟题,但是数据比较大,如果用二维数组的话,会爆空间,想着能用哈希表压缩一下空间,使空间集中

但是没有得到满分,不知道哪里出了问题,可能是哈希冲突吧

Atcoder beginner contest 303_第1张图片

代码如下: 

#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;
}

然后正当我一筹莫展时 

Atcoder beginner contest 303_第2张图片

我通过看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;
}

你可能感兴趣的:(Atcoder,Beginner,Contest,c++,算法,动态规划,vector,set)