• Codeforces Round #222 (Div. 2) 题解


    A.Playing with Dice

    题意:输入ab,问1~6中有几个数离a近,几个数距离ab相等,几个数离b近

    思路:直接暴力答案

    代码:

    #include <bits/stdc++.h>using namespace std;
    int main()
    {
        int a,b;
        scanf("%d%d", &a, &b);
        int as = 0, qw = 0, zx = 0;
        for(int i = 1; i <= 6; i++) {
            int aa = abs(a - i);
            int bb = abs(b - i);
            if(aa < bb) as++;
            if(aa == bb) qw++;
            if(aa > bb) zx++;
        }
        printf("%d %d %d
    ",as,qw,zx);
    return 0;
    }
    View Code

    C.Maze

    题意:给一个n*m的地图,地图中’.’表示空地,’#’表示墙,现在空地为一个联通块,现在需要在k个地方建墙,是的剩余的部分还是一个联通块

    思路:假设空地的格数为s个,那么多搜s-k格,广搜到的部分就是最后剩下的联通块,其他的都为墙

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef pair<int, int> pii;
    int n, m, k;
    char mp[505][505];
    int vis[505][505];
    int top;
    int dx[10] = {1,-1,0,0};
    int dy[10] = {0,0,1,-1};
    int sum ;
    void bfs(int x,int y)
    {
        queue<pii> q;
        while(!q.empty())q.pop();
        pii as = make_pair(x,y);
        vis[x][y] = 1;
        q.push(as);
        int cnt = 0;
        sum -= k;
        while(!q.empty() && cnt < sum){
            pii now = q.front();
            mp[now.first][now.second] = '!';
            cnt ++;
            q.pop();
            for(int i = 0; i < 4; i++){
                int xx = now.first + dx[i];
                int yy = now.second + dy[i];
                if(xx < 1 || xx > n || yy < 1 || yy > m || mp[xx][yy] == '#' || vis[xx][yy])continue;
                vis[xx][yy] = 1;
                pii as = make_pair(xx, yy);
                q.push(as);
            }
        }
    }
    int main()
    {
        scanf("%d%d%d", &n, &m, &k);
        sum = 0;
        for(int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                cin >> mp[i][j];
                if(mp[i][j] == '.')sum ++;
            }
        }
        bool ok = true;
        for(int i = 1; i <= n && ok; i++) {
            for(int j = 1; j <= m && ok; j++) {
                if(vis[i][j] || mp[i][j] == '#')continue;
                bfs(i, j);
                ok = false;
            }
        }
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                if(mp[i][j] == '!')mp[i][j] = '.';
                else if(mp[i][j] == '.') mp[i][j] = 'X';
                printf("%c",mp[i][j]);
            }
            puts("");
        }
        return 0;
    }
    View Code

    D.Preparing for the Contest

    题意:有n个bug,每个bug有一定的困难值,有m个人,每个人都有能力值bi以及费用ci,每个人只需要花一次费用就可以一直修bug,但是他只能修小于等于他能力值的bug,一个bug修一天,现在有s圆,问最少几天,并且费用在s以内,可以把bug修完,打印方案

    思路:因为天数是单调的,所以二分枚举,我们对问题的难度进行排序,前mid天给一个人修,就这样一直找费用最小的人,费用最小的人用优先队列维护,每次弹出最便宜的

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5+7;
    int n, m, s;
    int ans[maxn];
    struct node
    {
        int b, val, id;
        bool operator <(node a) const
        {
            return val>a.val;
        }
    }a[maxn], c[maxn];
    bool cmp(node A, node B)
    {
        return A.b > B.b;
    }
    bool check(int t)
    {
        int res = 0;
        priority_queue<node> q;
        while(!q.empty())q.pop();
        for(int i = 1, j = 1; j <= m; j += t) {
            while(i <= n && a[j].b <= c[i].b) {
                q.push(c[i]);
                i++;
            }
            if(q.empty()) return false;
            node as = q.top(); q.pop();
            res += as.val;
            for(int k = j; k < min(j+t, m+1); k++) {
                ans[a[k].id] = as.id;
            }
            if(res > s) return false;
        }
        return true;
    }
    int main()
    {
        scanf("%d%d%d", &n, &m, &s);
        for(int i = 1; i <= m; i++) {
            scanf("%d", &a[i].b);
            a[i].id = i; a[i].val = 0;
        }
        for(int i = 1; i <= n; i++) {
            scanf("%d", &c[i].b);
        }
        for(int i = 1; i <= n; i++) {
            scanf("%d", &c[i].val);
            c[i].id = i;
        }
        sort(a + 1, a + 1 + m, cmp);
        sort(c + 1, c + 1 + n, cmp);
        int ok = 0;
        for(int i = 1; i <= n; i++) {
            if(c[i].b >= a[1].b && c[i].val <= s){
                ok = 1;
                break;
            }
        }
        if(!ok) {
            puts("NO");
            return 0;
        }
        int L = 1, R = m, res = 0;
        while(L <= R) {
            int mid = (L + R) >> 1;
            if(check(mid)) {
                R = mid - 1;
                res = mid;
            }
            else L = mid + 1;
        }
        check(res);
        puts("YES");
        for(int i = 1; i <= m; i++) {
            if(i > 1)printf(" ");
            printf("%d",ans[i]);
        }
        puts("");
        return 0;
    }
    View Code

    E. Captains Mode

    题意:有n个英雄,每个英雄有他的力量值,有两队进行bp,一共m(20)次bp操作,问在m次bp后1队的英雄力量总和减去二队的力量总和最大值为多少

    思路:因为m很小,所以状压,dp[i]表示状态为i时,1队减2队的最大值,因为一个想让差值增大,一个想减小,所以1队时的转移为dp[i] = max(dp[i | (1<<j)] + s[j + 1])为2队时中间的符号相减,倒着枚举状态,使后面的状态在前面都算过了

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e6+7;
    int s[maxn];
    int dp[1<<21];
    int op[25],a[25];
    bool cmp(int x,int y)
    {
        return x > y;
    }
    int gett(int x)
    {
        int res = 0;
        for(; x; res++)x &= x - 1;
        return res;
    }
    int main()
    {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &s[i]);
        }
        sort(s + 1, s + 1 + n, cmp);
        int m;
        scanf("%d", &m);
        for(int i = 0; i < m; i++) {
            char ch;
            scanf("
    %c%d", &ch, &a[i]);
            op[i] = (ch == 'p');
        }
        dp[(1 << m) - 1] = 0;
        for(int i = (1<<m) - 2; i >= 0; i--) {
            int num = gett(i);
            if(a[num] == 1) {
                dp[i] = -0x3f3f3f3f;
                for(int j = 0; j < m; j++) {
                    if((i & (1<<j)) == 0)
                        dp[i] = max(dp[i], dp[i | (1<<j)] + op[num] * s[j + 1]);
                }
            }
            else {
                dp[i] = 0x3f3f3f3f;
                for(int j = 0; j < m; j++) {
                    if((i & (1<<j)) == 0)
                        dp[i] = min(dp[i], dp[i | (1<<j)] - op[num] * s[j + 1]);
                }
            }
        }
        printf("%d
    ",dp[0]);
        return 0;
    }
    View Code
  • 相关阅读:
    第04章-面向切面的Spring
    第03章-高级装配
    第02章-装配Bean
    第01章-Spring之旅
    IntelliJ IDEA打可运行jar包时的错误
    序列化+fastjson和java各种数据对象相互转化
    TinkerPop中的遍历:图的遍历策略
    TinkerPop中的遍历:图的遍历中谓词、栅栏、范围和Lambda的说明
    asp.net动态网站repeater控件使用及分页操作介绍
    HTML入门标签汇总
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/10409569.html
Copyright © 2020-2023  润新知