#51nod上topcoder练习记

 

好久没刷51nod了,又听说topcoder有很多好题。那么就来51nod上刷吧。(那个客户端搞得有点烦(看不懂))

 

[1366 贫富差距]

当图不连通的时候,答案为无穷大。

当图连通时,两个点之间的最大差值就是最短路长度乘上 $d$,跑floyd再看最短路的最大值即可。

 1 #include <bits/stdc++.h>
 2 
 3 const int N = 55;
 4 const int INF = 0x3f3f3f3f;
 5 
 6 char s[N];
 7 int mp[N][N], fa[N], n;
 8 
 9 int getfa(int x) {
10     return x == fa[x] ? x : fa[x] = getfa(fa[x]);
11 }
12 
13 void unit(int x, int y) {
14     x = getfa(x), y = getfa(y);
15     fa[x] = y;
16 }
17 
18 void floyd() {
19     for (int k = 1; k <= n; k++)
20         for (int i = 1; i <= n; i++)
21             for (int j = 1; j <= n; j++)
22                 mp[i][j] = std::min(mp[i][j], mp[i][k] + mp[k][j]);
23 }
24 
25 int main() {
26     int T;
27     scanf("%d", &T);
28     while (T--) {
29         int d;
30         scanf("%d%d", &n, &d);
31         for (int i = 1; i <= n; i++) fa[i] = i;
32         for (int i = 1; i <= n; i++) {
33             scanf("%s", s + 1);
34             for (int j = 1; j <= n; j++) {
35                 if (s[j] == 'Y' && i != j)
36                     mp[i][j] = d, unit(i, j);
37                 else if (i != j)
38                     mp[i][j] = INF;
39                 else 
40                     mp[i][j] = 0;
41             }
42         }
43         int cnt = 0;
44         for (int i = 1; i <= n; i++)
45             if (getfa(i) == i) cnt++;
46         if (cnt > 1) {
47             puts("-1");
48             continue;
49         }
50         floyd();
51         int ans = 0;
52         for (int i = 1; i <= n; i++)
53             for (int j = 1; j <= n; j++)
54                 if (mp[i][j] < INF) 
55                     ans = std::max(ans, mp[i][j]);
56         printf("%d\n", ans);
57     }
58     return 0;
59 }
View Code

 

[1402 最大值]

可以发现当限制比数字的位置还大时,这个限制就没用了。

然后有时候到不了极限数据,因为被前面的卡住了或者被后面的卡住了。

即 $t_i - t_{i - 1} > x_i - x_{i - 1}$,$t_i - t_{i + 1} > x_{i + 1} - x_i$ 这两种情况。暴力更新即可。

然后最大值就在每两个限制之间得到。

#include <bits/stdc++.h>

const int N = 55;

int x[N], t[N];

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, m;
        scanf("%d%d", &n, &m);
        int cnt = 1;
        x[cnt] = 1, t[cnt] = 0;
        for (int i = 1; i <= m; i++) {
            int a, b;
            scanf("%d%d", &a, &b);
            if (b < a - 1)
                x[++cnt] = a, t[cnt] = b;
        }
        if (!cnt) {
            printf("%d\n", n - 1);
            continue;
        }
        for (int i = 1; i <= cnt; i++) {
            if (i > 1 && t[i] - t[i - 1] > x[i] - x[i - 1])
                t[i] = t[i - 1] + x[i] - x[i - 1];
            if (i < cnt && t[i] - t[i + 1] > x[i + 1] - x[i]) {
                t[i] = t[i + 1] + x[i + 1] - x[i];
                i = 0;
            }
        }
        int ans = 0;
        for (int i = 1; i < cnt; i++) 
            ans = std::max(ans, (t[i] + t[i + 1] - x[i] + x[i + 1]) / 2);
        ans = std::max(ans, t[cnt] + n - x[cnt]);
        printf("%d\n", ans);
    }
}
View Code

 

[1418 放球游戏]

一种球的贡献最多为 $2$,那么统计球的个数即可。

#include <bits/stdc++.h>

const int N = 60;
char s[N];
int cnt[3];

inline int getid(char ch) {
    if (ch == 'R') return 0;
    if (ch == 'G') return 1;
    return 2;
}    

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%s", s + 1);
        int n = strlen(s + 1);
        if (n == 1) {
            puts("0");
            continue;
        }
        if (n == 2) {
            puts("1");
            continue;
        }
        for (int i = 0; i < 3; i++)
            cnt[i] = 0;
        for (int i = 1; i <= 2; i++)
            cnt[getid(s[i])]++;
        int ans = 1;
        for (int i = 3; i <= n; i++) {
            for (int j = 0; j < 3; j++)
                ans += std::min(cnt[j], 2);
            cnt[getid(s[i])]++;
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

[1487 占领资源]

和一个点会有交集的点最多只有 $k^2$ 个,特判这些点,再去其他点中最大的那个即可。

#include <bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second

const int N = 110;
const int M = 1e4 + 7;
int dx[11], dy[11];
char s[N];
int mp[N][N];
std::vector<int> belong[M];
std::pii p[M];
std::map<std::pii, int> gong;

int main() {
    freopen("in.txt", "r", stdin);
     int T;
     scanf("%d", &T);
     while (T--) {
         int n, m, k;
         scanf("%d%d%d", &n, &m, &k);
         for (int i = 1; i <= n; i++) {
             scanf("%s", s + 1);
             for (int j = 1; j <= m; j++)
                 mp[i][j] = s[j] - '0';
         }
         for (int i = 1; i <= k; i++)
             scanf("%d%d", &dx[i], &dy[i]);
         for (int i = 1; i <= n; i++)
             for (int j = 1; j <= m; j++) {
                 int pos = (i - 1) * m + j;
                 p[pos].se = pos;
                 p[pos].fi = 0;
                 for (int z = 1; z <= k; z++) {
                     int x = i + dx[z], y = j + dy[z];
                     if (x <= 0 || x > n || y <= 0 || y > m) continue;
                     belong[(x - 1) * m + y].push_back(pos);
                     p[pos].fi += mp[x][y];
                 }
             }
         int ans = 0;
         std::sort(p + 1, p + n * m + 1, std::greater<std::pii>());
         for (int cnt = 1; cnt <= n * m; cnt++) {
             gong.clear();
             int pos = p[cnt].se;
             int i = pos / m, j = pos % m;
             if (!j) j = m;
             else i++;
             if (p[cnt].fi + p[1].fi <= ans) continue;
             for (int z = 1; z <= k; z++) {
                 int x = i + dx[z], y = j + dy[z];
                 if (x <= 0 || x > n || y <= 0 || y > m) continue;
                 int ne = (x - 1) * m + y;
                 for (int tong: belong[ne]) {
                     if (pos == tong) continue;
                     gong[std::pii(std::min(pos, tong), std::max(pos, tong))] -= mp[x][y];
                 }
             }
             for (int z = 1; z <= k * k + 1; z++) {
                 if (z == cnt) continue;
                 int id = p[z].se;
                 ans = std::max(ans, gong[std::pii(std::min(pos, id), std::max(pos, id))] + p[cnt].fi + p[z].fi);
                 if (!gong.count(std::pii(std::min(pos, id), std::max(pos, id)))) break;
             }
         }
         for (int i = 1; i <= n * m; i++)
             belong[i].clear(), p[i].fi = p[i].se = 0;
         printf("%d\n", ans);
     }
     return 0;
}
View Code

 

[1445 变色DNA]

唉,这都想不出来,好菜啊...

$i$ 到 $j$ 的代价就等于第 $i$ 行 $0$ 到 $j - 1$ 有多少个 'Y'。要优先走这条边就要付出这么多代价,然后floyd就好了

#include <bits/stdc++.h>

const int N = 55;
const int INF = 0x3f3f3f3f;
int mp[N][N];
char s[N];

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        memset(mp, 0x3f, sizeof mp);
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%s", s + 1);
            int cost = 0;
            for (int j = 1; j <= n; j++)
                if (s[j] == 'Y')
                    mp[i][j] = cost++;
        }
        for (int i = 1; i <= n; i++)
            mp[i][i] = 0;
        for (int k = 1; k <= n; k++)
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= n; j++)
                    mp[i][j] = std::min(mp[i][j], mp[i][k] + mp[k][j]);
        printf("%d\n", mp[1][n] == INF ? -1 : mp[1][n]);
    }
    return 0;
}
View Code

 

[1351 吃点心]

当取的 $low$ 值之和不小于 $x$ 时,为一个方案

当不取的 $high$ 值之和不大于 $c - x$ 时,为一个方案

这两种情况可以独立来算,对 $low$ 和 $high$ 分别排个序就ok了。

#include <bits/stdc++.h>

const int N = 55;

int low[N], high[N];

int main() {
    //freopen("in.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, c, x;
        scanf("%d%d%d", &n, &c, &x);
        for (int i = 1; i <= n; i++)
            scanf("%d%d", low + i, high + i);
        int ans = n;
        std::sort(low + 1, low + 1 + n);
        std::sort(high + 1, high + 1 + n);
        for (int i = n, sum = 0; i; i--) {
            sum += low[i];
            if (sum >= x) {
                ans = std::min(n - i + 1, ans);
                break;
            }
        }
        for (int i = 1, sum = 0; i <= n; i++) {
            sum += high[i];
            if (c - sum < x) {
                ans = std::min(ans, n - i + 1);
                break;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

/***
34
32
28
***/
View Code

 

[1337 翻转游戏]

当不出现问号时,该开时开,该关时关就OK了。

当出现了问号时,如果上一轮的该位置状态为 '-' 且这一轮有开灯的操作,那么这一位就可以是 '?',或者该位置状态为 '+' 且这一轮有关灯的操作,同理也是 '?'

多一个 '?' 就可以让之后尽量少操作。

#include <bits/stdc++.h>

const int N = 55;
char mp[N][N], s[N];

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
            scanf("%s", mp[i] + 1);
        for (int i = 1; i <= m; i++)
            s[i] = '-';
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            bool open = 0, close = 0;
            for (int j = 1; j <= m; j++) {
                if (s[j] == '-' && mp[i][j] == '+')
                    open = 1;
                if (s[j] == '+' && mp[i][j] == '-')
                    close = 1;
            }
            if (open) ans++;
            if (close) ans++;
            ans++;
            for (int j = 1; j <= m; j++) {
                if (mp[i][j] == '?') {
                    if (close && s[j] == '+')
                        s[j] = '?';
                    if (open && s[j] == '-')
                        s[j] = '?';
                } else {
                    s[j] = mp[i][j];
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

[1388 六边形平面]

答案最多为 3,为 3 时即存在奇环,bfs判一下即可。

#include <bits/stdc++.h>

const int N = 77;
const int dir[6][2] = {{-1, 0}, {-1, 1}, {0, 1}, {1, 0}, {1, -1}, {0, -1}};
char s[N][N];
int n, dis[N][N];

bool bfs(int dx, int dy) {
    std::queue< std::pair<int, int> > que;
    que.push(std::pair<int, int>(dx, dy));
    while (!que.empty()) {
        std::pair<int, int> p = que.front(); que.pop();
        int i = p.first, j = p.second;
        for (int k = 0; k < 6; k++) {
            int x = i + dir[k][0], y = j + dir[k][1];
            if (x < 1 || y < 1 || x > n || y > n || s[x][y] == '-') continue;
            if (dis[x][y]) {
                if (dis[x][y] % 2 == dis[i][j] % 2) return true;
                continue;
            }
            que.push(std::pair<int, int>(x, y));
            dis[x][y] = dis[i][j] + 1;
        }
    }
    return false;
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            scanf("%s", s[i] + 1);
            for (int j = 1; j <= n; j++)
                if (s[i][j] == 'X') ans = 1;
        }
        for (int i = 1; i <= n; i++) 
            for (int j = 1; j <= n; j++) if (s[i][j] == 'X') {
                    for (int k = 0; k < 6; k++) {
                        int x = i + dir[k][0], y = j + dir[k][1];
                        if (x < 1 || y < 1 || x > n || y > n || s[x][y] == '-') continue;
                        ans = 2;
                    }
                }
        memset(dis, 0, sizeof(dis));
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                if (s[i][j] == 'X' && dis[i][j] == 0)
                    if (bfs(i, j)) ans = 3;
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

posted @ 2019-10-21 00:35  Mrzdtz220  阅读(196)  评论(0)    收藏  举报