atcoder abc 369

A 369

问题:

思路:暴力枚举

代码:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int a, b;
    cin >> a >> b;
    int cnt = 0;
    for(int i = -1000; i <= 1000; i ++ ) {
        vector<int> aa;
        aa.push_back(a);
        aa.push_back(b);
        aa.push_back(i);
        sort(aa.begin(), aa.end());
        if(aa[1] - aa[0] == aa[2] - aa[1]) cnt ++;
    }
    cout << cnt << endl;
    return 0;
}

B Piano 3

问题:

思路:贪心的将手的初始位置设为第一个键位所在的位置

代码:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    vector<char> s(n + 1);
    for(int i = 1; i <= n; i ++ ) cin >> a[i] >> s[i];
    int cl = -1, cr = -1;
    int lastl = 0, lastr = 0;
    for(int i = 1; i <= n; i ++ ) {
        if(s[i] == 'L') {
            if(cl == -1) {
                cl = 0;
                lastl = a[i];
            } else {
                cl += abs(a[i] - lastl);
                lastl = a[i];
            }
        } else {
            if(cr == -1) {
                cr = 0;
                lastr = a[i];
            } else {
                cr += abs(a[i] - lastr);
                lastr = a[i];
            }
        }
    }

    cout << max(0, cl) + max(0, cr);
    return 0;
}

C Count Arithmetic Subarrays

问题:

思路:

开一个interval数组储存所有满足题意的子段

代码:

#include <bits/stdc++.h>

using namespace std;

int main() {
    int n;
    cin >> n;
    vector<long long> a(n + 2);
    a[n + 1] = 1e18;
    for(int i = 1; i <= n; i ++ ) cin >> a[i];
    long long ans = 0;
    int last = a[2] - a[1];
    int pos = 1;
    vector<pair<int, int>> interval;
    for(int i = 2; i <= n + 1; i ++ ) {
        if(a[i] - a[i - 1] != last) {
            last = a[i] - a[i - 1];
            interval.push_back({pos, i - 1});
            pos = i - 1;
        }
    }

    for(auto t: interval) {
        //cout << t.first << " " << t.second <<endl;
        int num = t.second - t.first + 1;
        ans += (long long)num * (num + 1) / 2;
    }
    cout << ans - interval.size() + 1;
    return 0;
}

D Bonus EXP

问题:

思路:动态规划dp[i][j][k]表示第i个位置的怪物我是选择击杀还是不击杀以及这是我击杀的第几个(奇数个,偶数个)怪物

问题:在状态定义时一定要清楚定义,例如本题调试中由于 击杀第几个怪物的定义不明确,导致代码出错 

以及在最开始dp[i][1][0]可能不会出现,因此要判断dp[i][1][0]之前的状态是否出现过

代码:

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

long long dp[N][3][3];//表示第i个我是选择击杀还是不击杀,以及这是我击杀的第几个怪物

int main() {
    int n;
    cin >> n;
    vector<long long> a(n + 1);
    bool flag = false;
    for(int i = 1; i <= n; i ++ ) cin >> a[i];
    for(int i = 1; i <= n; i ++ ) {
        dp[i][0][1] = max(dp[i - 1][1][1], dp[i - 1][0][1]);
        dp[i][0][0] = max(dp[i - 1][1][0], dp[i - 1][0][0]);
        dp[i][1][1] = max(dp[i - 1][1][0] + a[i], dp[i - 1][0][0] + a[i]);
        //dp[i][1][0] = max(dp[i - 1][1][1] + a[i] * 2, dp[i - 1][0][0] + a[i] * 2)
        if(dp[i - 1][1][1] != 0) dp[i][1][0] = max(dp[i][1][0], dp[i - 1][1][1] + a[i] * 2);
        if(dp[i - 1][0][1] != 0) dp[i][1][0] = max(dp[i][1][0], dp[i - 1][0][1] + a[i] * 2);
    }

    long long ans = 0;
    //n = 1;
    ans = max(dp[n][0][1], dp[n][0][0]);
    ans = max(ans, dp[n][1][0]);
    ans = max(ans, dp[n][1][1]);
    cout << ans << endl;
    //cout << dp[1][1][1] << endl;
    //cout << dp[2][1][0];
    //cout << dp[n][1][0];
    return 0;
}

E Sightseeing Tour

问题:

思路:floyd + 排列组合

黑色为必须经过的桥,不难想到,求最短路就是让红色的线最短,因此我们要准确的知道各个点之间的最短路。同时观察到n的范围很小,在o(n ^ 3)内,考虑floyd解决这个问题。并且不同的连点方式也会对答案造成影响,又注意到k,也就是固定的桥范围不超过5,并且q询问也很小,因此直接枚举所有的连点情况,先枚举桥的顺序,可以用next_permutation枚举,再用dfs枚举桥与桥之间的连接方式

代码:
 

#include <bits/stdc++.h>

using namespace std;

const int N = 410;
const int M = 2e5 + 10;

int g[N][N];
pair<int, int> b[M];
int len[M];

int main() {
    memset(g, 0x3f, sizeof g);
    int n, m;
    cin >> n >> m;

    for(int i = 1; i <= m; i ++ ) {
        int u, v, t;
        cin >> u >> v >> t;
        g[u][v] = min(g[u][v], t);
        g[v][u] = min(g[v][u], t);
        b[i] = {u, v};
        len[i] = t;
    }
    
    for(int i = 1; i <= n; i ++ ) g[i][i] = 0;
    for(int k = 1; k <= n; k ++ ) {
        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]);
            }
        }
    }//floyd 400^3

    int q;
    cin >> q;
    while(q -- ) {
        int k;
        cin >> k;
        vector<int> a(k + 1);
        long long ans = 1e18;
        long long tmp = 0;
        for(int i = 1; i <= k; i ++ ) {
            cin >> a[i];
            tmp += len[a[i]];
        }

        vector<int> alls(2 * (k + 1) + 5);
        alls[1] = 1;
        alls[2 * (k + 1)] = n; 
        function<void(int)> dfs = [&](int u) {
            if(u == k + 1) {
                long long res = tmp;
                for(int i = 2; i <= 2 * (k + 1); i ++ ) {
                    res += g[alls[i]][alls[i - 1]];
                }
                ans = min(ans, res);
                return;
            }
                for(int j = 1; j <= 2; j ++ ) {
                    if(j == 1) {
                        alls[2 * u] = b[u].first;
                        alls[2 * u + 1] = b[u].second;
                    } else {
                        alls[2 * u] = b[u].second;
                        alls[2 * u + 1] = b[u].first;
                    }
                    dfs(u + 1);
                }
        };
        do {
            dfs(1);
        } while(next_permutation(a.begin() + 1, a.end()));
        cout << ans << endl;
    }
    return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值