Codeforces Round #374 (Div. 2)(A-D)(水模拟 + 水模拟 + dfs & dp + 优先队列模拟)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ShadowGhostH/article/details/80228224

A

题意:记录被W分离的连续B的数目

思路:水题,读入模拟

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e5+7;

char s[maxn];
int ans[maxn];

int main()
{
    int n;
    cin>>n>>s;
    int cnt = 0, p = 0;
    for(int i=0; i<n; i++)
    {
        if(s[i] == 'B') cnt++;
        if(s[i] == 'W'){
            if(cnt){
                ans[p++] = cnt;
                cnt = 0;
            }
        }
    }
    if(cnt) ans[p++] = cnt;
    cout<<p<<endl;
    for(int i=0; i<p; i++)
    {
        if(i) cout<<" ";
        cout<<ans[i];
    }
    cout<<endl;
}

B

题意:输入密码时按照猜测密码长度升序输入,相同长度的猜测密码随机输入,输入错误k次之后会有5秒的不可输入时间,给出正确的密码和猜测的密码,问最少花多长时间和最多花多长时间能够猜对。

思路:最少时间就是输完所有比正确密码短的猜测密码后一次输入正确,最长时间就是输入所有小于等于正确密码长度后才正确。直接记录个数然后求值。

#include<bits/stdc++.h>
using namespace std;

const int maxn = 105;

string a[maxn], key;

int main()
{
    cin.sync_with_stdio(false);

    int n, k;
    cin>>n>>k;
    for(int i=0; i<n; i++)
        cin>>a[i];
    cin>>key;

    int p = unique(a, a+n) - a;

    int sum = 0;
    int minn = 0, maxx = -1;
    for(int i=0; i<p; i++)
    {
        if(a[i].size() < key.size()) minn++;
        if(a[i].size() <= key.size()) maxx++;
    }

    minn = minn + 5*(minn/k) + 1;
    maxx = maxx + 5*(maxx/k) + 1;

    cout<<minn<<" "<<maxx<<endl;
}

C

题意:给出一个有向图,每条边有边权,问从1到n的所有路径中,边权和不超过t,且经过城市最多的走法

思路:用dfs递归遍历所有的点,然后记录路径和路径上的边权,最后找到边权和不超过t路径最长的路径输出

给出一个用了c++ 11特性的大牛的代码,自己的有点丑

#include <bits/stdc++.h>
#define INF 1000000007
using namespace std;
typedef pair<int,int> ii;

vector<vector<ii> > graph;
vector<int> visit;
vector<vector<int> > cost, parent;
int n,m,t;

void dfs(int u){
    visit[u] = 1;
    for(ii e : graph[u]){
        int v = e.first,t = e.second;
        if(!visit[v])
            dfs(v);
        for(int i = 1;i<=n;i++){
            if(cost[v][i-1]+t < cost[u][i]){
                cost[u][i] = cost[v][i-1]+t;
                parent[u][i] = v;
            }
        }
    }
}

int main()
{
    cin >> n >> m >> t;
    graph.resize(n);
    for(int i = 0;i<m;i++){
        int a,b,t; cin >> a >> b >> t;
        --a,--b;
        graph[a].push_back({b,t});
    }
    visit.resize(n);
    cost.resize(n+1, vector<int>(n+1, INF));
    parent.resize(n+1, vector<int>(n+1, INF));
    cost[n-1][0] = 0;
    dfs(0);
    int j = 0;
    for(int i = 0;i<=n;i++){
        if(cost[0][i] <= t)
            j = i;
    }
    cout << j+1 << endl;
    int cur = 0;
    while(cur != n-1){
        cout << cur+1 << " ";
        cur = parent[cur][j--];
    }
    cout << n << endl;
    return 0;
}

D

扫描二维码关注公众号,回复: 3209512 查看本文章

题意:给出一个数列,我们可以进行k次操作,操作为任选一个数加上或减去x,问k次操作后使得数列积最小,输出数列。

思路:每次我们都找绝对值最小的那个数,因为操作它对数列的贡献是其余元素的积,最小的数的贡献最大,如果当前数列积为正,我们使数靠近0,积为负我们使数远离0

#include<bits/stdc++.h>
#define LL long long
using namespace std;

const int maxn = 2e5+5;

struct Node{
    LL val;
    int id;
    bool operator < (const Node& b) const{
        return abs(val) > abs(b.val);
    }
}a[maxn];

priority_queue<Node> q;

int main()
{
    cin.sync_with_stdio(false);

    int n, k, x, cnt = 0, minn = 0;

    cin>>n>>k>>x;

    for(int i=0; i<n; i++)
    {
        cin>>a[i].val;
        a[i].id = i;
        if(a[i].val<0) cnt++;
        q.push(a[i]);
    }

    while(k--)
    {
        Node now = q.top();
        q.pop();
        if(now.val >= 0){
            if(cnt&1) a[now.id].val += x;
            else a[now.id].val -= x;
            if(a[now.id].val < 0) cnt++;
            q.push(a[now.id]);
        }
        else {
            if(cnt&1) a[now.id].val -= x;
            else a[now.id].val += x;
            if(a[now.id].val >= 0) cnt--;
            q.push(a[now.id]);
        }
    }

    for(int i=0; i<n; i++)
        printf("%I64d%c", a[i].val, i==n-1?'\n':' ');

    return 0;
}


猜你喜欢

转载自blog.csdn.net/ShadowGhostH/article/details/80228224
今日推荐