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\n",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("\n%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\n",dp[0]);
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/lalalatianlalu/p/10409569.html