[Atcoder] ABC244

image

A - Last Letter

image

思路

输出字符串的最后一个字符

代码

#include<bits/stdc++.h>
#include <iostream>
#include <ctime>
using namespace std;
//==========================================
const int maxn = 1e5+5;
signed main(signed argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
#ifdef LOCAL
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
    //======================================
    string str;
    int n;
    cin >> n;
    cin >> str;
    cout << str[str.length() - 1] << endl;
    //======================================

    return 0;   
}

/*DETAILS

*/

B - Go Straight and Turn Right

image
给出一个字符串,S代表直走,R代表转方向90度
求最后的x,y的坐标

思路

直接模拟即可

代码

#include<bits/stdc++.h>
#include <iostream>
#include <ctime>
using namespace std;
//==========================================
const int maxn = 1e5+5;
int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};
signed main(signed argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
#ifdef LOCAL
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
    //======================================
    int n;
    string str;
    cin >> n;
    cin >> str;
    int len = str.length();
    int flag = 2;
    int x = 0, y = 0;
    for(int i = 0; i < len; i ++) {
        if(str[i] == 'R') {
            if(flag == 1) flag = 2;
            else if(flag == 2) flag = 3;
            else if(flag == 3) flag = 4;
            else if(flag == 4) flag = 1;
        }
        else {
            //cout << flag << endl;
            x += dx[flag - 1], y += dy[flag - 1];
            //cout << x << " " << y << endl;
        }
    }
    cout << x << " " << y << endl;
    //======================================

    return 0;   
}

/*DETAILS

*/

C - Yamanote Line Game

image
交互题,有1~2n+1共2n+1个数字,你和对手轮流说出一个没说过的数字,直到最后没数字可以说,模拟这个过程.

思路

注意输入输出的顺序即可,每次出现一个数字就在mp里标记掉,每次循环找没出现的数字输出
当输入为0的时候break

代码

#include<bits/stdc++.h>
#include <iostream>
#include <ctime>
using namespace std;
//==========================================
const int maxn = 1e5+5;
map<int, int> mp;
signed main(signed argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    //======================================
    int n;
    cin >> n;
    int tmp;
    int t = 2 * n - 1;
    while(t --) {
        for(int i = 1; i <= 2 * n + 1; i ++) {
            if(!mp[i]) {
                cout << i << endl;
                mp[i] = 1;
                fflush(stdout);
                break;
            }
        }
        cin >> tmp;
        if(tmp == 0) break;
        mp[tmp] = 1;
    }
    //======================================

    return 0;   
}

D - Swap Hats

image
给出三个人当前戴的帽子颜色和应该戴的帽子颜色,问能否在交换1e18次后三个人都是应该戴的帽子的颜色

思路

给出的s1,s2,s3是R,G,B的排列,t也是
那么按是否相同来划分,只会出现四种情况
都不相同, 如:s1 != t1, s2 != t2, s3 != t3
有一个相同,如:s1 == t1, s2 != t2, s3 != t3
有两个相同,如:s1 == t1, s2 == t2, s3 != t3
三个都相同,如:s1 == t1, s2 == t2, s3 == t3
题目要求必须交换1e18次
模拟一下就可以发现,只有在一个相同的情况下才会失败,其余都是成功

代码

#include<bits/stdc++.h>
#include <iostream>
#include <ctime>
using namespace std;
//==========================================
const int maxn = 1e5+5;
signed main(signed argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    //======================================
    char s1, s2, s3;
    char t1, t2, t3;
    int fg = 0;
    cin >> s1 >> s2 >> s3;
    cin >> t1 >> t2 >> t3;
    if(s1 == t1) fg ++;
    if(s2 == t2) fg ++;
    if(s3 == t3) fg ++;
    if(fg == 1) cout << "No" << endl;
    else cout << "Yes" << endl;

    //======================================

    return 0;   
}

E - King Bombee

image
给出n个点,m条边的无向图,问满足以下条件的路径数
1、Ai是1~n之间的整数
2、A0=s
3、Ak=t
4、Ai~Ai+1之间有边连接
5、x号节点出现的次数是偶数(可能是0)

思路

一共最多是2000个点,2000条边,而路径数会很大,可以尝试去dp路径数
发现是可行的
我们可以令dp[i][j]表示走到第i个节点的步数为j的路径数
但是这样肯定不够,题目还有一个经过x点的次数不能是奇数的条件
所以就可以多加一维来表示经过x点的次数是奇数次还是偶数次
那么状态就为dp[i][j][z]表示走到第i个节点的步数为j,且z=1时表示经过x节点的次数是奇数次,z=0时表示经过x节点的次数是偶数次
状态转移方程就为,当u!=x时,dp[i][j][z] += dp[u][j - 1][z];
当u==x时,dp[i][j][z] += dp[u][j - 1][z ^ 1];
边界条件是从s号节点开始走,那么就是dp[s][1][0] = 1;
最终答案就是走到t号节点的步数为k+1且经过x号节点的次数为偶数次的路径数,即dp[t][k + 1][0]

代码

#include<bits/stdc++.h>
#include <iostream>
#include <ctime>
using namespace std;
//==========================================
const int maxn = 2010, mod = 998244353;
int e[2 * maxn], ne[2 * maxn], h[maxn], idx;
void add(int x, int y) {
    e[idx] = y, ne[idx] = h[x], h[x] = idx ++;
}
int dp[maxn][maxn][3];
signed main(signed argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
#ifdef LOCAL
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
    //======================================
    int n, m, k, s, t, x;
    cin >> n >> m;
    cin >> k >> s >> t >> x;
    int a, b;
    memset(h, -1, sizeof h);
    for(int i = 1; i <= m; i ++) {
        cin >> a >> b;
        add(a, b);
        add(b, a);
        //dp[a][b] = 1;
        //dp[b][a] = 1;
    }
    dp[s][1][0] = 1;
    for(int j = 2; j <= k + 1; j ++) {
        for(int i = 1; i <= n; i ++) {
            for(int z = h[i]; z != -1; z = ne[z]) {
                int u = e[z];
                if(u != x) {
                    dp[i][j][0] += dp[u][j - 1][0];
                    dp[i][j][0] %= mod;
                    dp[i][j][1] += dp[u][j - 1][1];
                    dp[i][j][1] %= mod;
                }
                else {
                    dp[i][j][0] += dp[u][j - 1][1];
                    dp[i][j][0] %= mod;
                    dp[i][j][1] += dp[u][j - 1][0];
                    dp[i][j][1] %= mod;
                }
            }
        }
    }
    //cout << dp[s][k] << " " << dp[k][t] << endl;
    cout << dp[t][k + 1][0] % mod << endl;
    
    //======================================

    return 0;   
}

F - Shortest Good Path

image
给出一个n个点m条边的无向图,还有一个长度为n的01序列S
找出满足以下条件的最短路径长度之和
1、若Si=0,那么路径中出现了偶数个i
2、若Si=1,那么路径中出现了奇数个i

思路

这题其实还没搞特别懂,后面想透彻了再完善吧。。。
状压dp
f[i][j]表示当前状态为i,路径中最后一个点在j的最短路径长度,i中第k位为0说明这个点在路径中有偶数个,为1说明有奇数个。

代码

#include<bits/stdc++.h>
#include <iostream>
#include <ctime>
using namespace std;
//==========================================
const int maxn = 17, INF = 0x3f3f3f3f;
typedef long long ll;
typedef pair<int, int> PII;
vector<int> g[maxn];
int f[1 << maxn][maxn];
signed main(signed argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
#ifdef LOCAL
    freopen("in.in", "r", stdin);
    freopen("out.out", "w", stdout);
#endif
    //======================================
    int n, m;
    cin >> n >> m;
    while(m --) {
        int a, b;
        cin >> a >> b;
        a --, b --;
        g[a].push_back(b), g[b].push_back(a);
    } 
    memset(f, 0x3f, sizeof f);
    queue<PII> q;
    for(int i = 0; i < n; i ++) {
        f[1 << i][i] = 1;
        q.push({1 << i, i});
    }
    while(!q.empty()) {
        auto t = q.front();
        q.pop();
        int state = t.first, ed = t.second;
        for(auto e : g[ed]) {
            int nstate = state ^ (1 << e);
            if(f[nstate][e] == INF) {
                f[nstate][e] = f[state][ed] + 1;
                q.push({nstate, e});
            }
        }
    }
    ll res = 0;
    for(int i = 1; i < (1 << n); i ++) {
        res += *min_element(f[i], f[i] + n);
    }
    cout << res << endl;
    //======================================

    return 0;   
}
posted @ 2022-03-21 11:26  行舟C  阅读(206)  评论(0)    收藏  举报