zoukankan      html  css  js  c++  java
  • [Offer收割]编程练习赛33

    矩阵游戏II

    把每列的数字加起来当一行处理。因为每次操作两列,所以最后最多剩下一个负数。如果负数的个数是偶数,直接所有数字的绝对值加起来即可;若负数个数为奇数,把所有数的绝对值加起来减去其中最小的绝对值的两倍即可。

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    int a[205][205];
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
    #endif
        int n;
        scanf("%d", &n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                scanf("%d", &a[i][j]);
            }
        }
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < n; j++) {
                a[0][j] += a[i][j];
            }
        }
        int cnt = 0, ans = 0, min = 1000000;
        for (int i = 0; i < n; i++) {
            if (a[0][i] < 0) {
                cnt++;
                a[0][i] = -1 * a[0][i];
            }
            ans += a[0][i];
            if (a[0][i] < min) {
                min = a[0][i];
            }
        }
        if (cnt % 2 != 0) {
            ans -= 2 * min;
        }
        printf("%d
    ", ans);
        return 0;
    }
    View Code

    是二叉搜索树吗?

    先判断树:首先判断是不是只有一个点没有父亲,然后判断从这个没有父亲的点dfs能否访问到其他所有的点。

    二叉树:每个点最多两个儿子就可以了。

    二叉搜索树:左子树最大的点小于根节点,右子树最小的点大于根节点。

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<vector>
    #include<algorithm>
    using namespace std;
    vector<int> G[10005];
    bool f[10005];
    int n, t;
    int max_[10005], min_[10005];
    bool erchashucuowu() {
        for (int i = 1; i <= n; i++) {
            if (G[i].size() > 2) {
                return true;
            }
        }
        return false;
    }
    void dfsmax(int r) {
        int ret = r;
        for (int i = 0; i < G[r].size(); i++) {
            dfsmax(G[r][i]);
            if (max_[G[r][i]] > ret) {
                ret = max_[G[r][i]];
            }
        }
        max_[r] = ret;
    }
    void dfsmin(int r) {
        int ret = r;
        for (int i = 0; i < G[r].size(); i++) {
            dfsmin(G[r][i]);
            if (min_[G[r][i]] < ret) {
                ret = min_[G[r][i]];
            }
        }
        min_[r] = ret;
    }
    bool bushisousuoshu(int r) {
        if (G[r].size() == 0) {
            return false;
        }
        if (G[r].size() == 1) {
            if (G[r][0] < r) {
                if (max_[G[r][0]] > r) {
                    return true;
                }
            } else {
                if (min_[G[r][0]] < r) {
                    return true;
                }
            }
            return bushisousuoshu(G[r][0]);
        }
        if (max_[G[r][0]] > r) {
            return true;
        }
        if (min_[G[r][1]] < r) {
            return true;
        }
        return (bushisousuoshu(G[r][0]) || bushisousuoshu(G[r][1]));
    }
    void dfs(int r) {
        printf("(");
        printf("%d", r);
        if (G[r].size() == 0) {
            printf("()()");
        }
        if (G[r].size() == 1) {
            if (G[r][0] < r) {
                dfs(G[r][0]);
                printf("()");
            } else {
                printf("()");
                dfs(G[r][0]);
            }
        }
        if (G[r].size() == 2) {
            dfs(G[r][0]);
            dfs(G[r][1]);
        }
        printf(")");
    }
    void jianchashu(int r) {
        if (f[r]) {
            return;
        }
        f[r] = true;
        for (int i = 0; i < G[r].size(); i++) {
            jianchashu(G[r][i]);
        }
    }
    bool jianchashushu() {
        for (int i = 1; i <= n; i++) {
            if (!f[i]) {
                return false;
            }
        }
        return true;
    }
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
    #endif
        scanf("%d", &t);
        while (t--) {
            scanf("%d", &n);
            for (int i = 1; i <= n; i++) {
                G[i].clear();
            }
            memset(f, true, sizeof(f));
            for (int i = 1; i < n; i++) {
                int a, b;
                scanf("%d%d", &a, &b);
                G[a].push_back(b);
                f[b] = false;
            }
            for (int i = 1; i <= n; i++) {
                sort(G[i].begin(), G[i].end());
            }
            int cnt = 0, id = -1;
            for (int i = 1; i <= n; i++) {
                if (f[i]) {
                    cnt++;
                    id = i;
                }
            }
            if (cnt != 1) {
                printf("ERROR1
    ");
                continue;
            }
            memset(f, false, sizeof(f));
            jianchashu(id);
            if (!jianchashushu()) {
                printf("ERROR1
    ");
                continue;
            }
            if (erchashucuowu()) {
                printf("ERROR2
    ");
                continue;
            }
            dfsmax(id);
            dfsmin(id);
            if (bushisousuoshu(id)) {
                printf("ERROR3
    ");
                continue;
            }
            dfs(id);
            printf("
    ");
        }
        return 0;
    }
    View Code

    方格取数

    动态规划:dp[i][j][k]表示走到第i个斜行,两条路分别位于第i斜行的第j和第k个方格。为保证不相交,设j<k。j和k分别可能由上一行的格子向右或向下走到,共4种前状态,取其中最大值加上jk两个方格中的数字即可。

    因为n最大为400,数组开全会MLE。考虑到每次状态转移的时候只会用到i-1中的值,所以可以把dp开成[2][400][400],两个数组轮换使用。

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    int a[205][205], dp[2][405][405];
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
    #endif
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                scanf("%d", &a[i][j]);
            }
        }
        memset(dp, 0, sizeof(dp));
        dp[1][1][1] = a[1][1];
        for (int i = 2; i < 2 * n - 1; i++) {
            int m = i < n ?  i : 2 * n - i;
            for (int j = 1; j < m; j++) {
                for (int k = j + 1; k <= m; k++) {
                    int x1, x2, y1, y2, tmp = 0, last = (i - 1) % 2;
                    if (i <= n) {
                        x1 = i - j + 1;
                        y1 = 1 + j - 1;
                        x2 = i - k + 1;
                        y2 = 1 + k - 1;
                        if (dp[last][j][k] > tmp) {
                            tmp = dp[last][j][k];
                        }
                        if (dp[last][j - 1][k - 1] > tmp) {
                            tmp = dp[last][j - 1][k - 1];
                        }
                        if (dp[last][j][k - 1] > tmp) {
                            tmp = dp[last][j][k - 1];
                        }
                        if (dp[last][j - 1][k] > tmp) {
                            tmp = dp[last][j - 1][k];
                        }
                    } else {
                        x1 = n - j + 1;
                        y1 = i - n + j;
                        x2 = n - k + 1;
                        y2 = i - n + k;
                        if (dp[last][j][k] > tmp) {
                            tmp = dp[last][j][k];
                        }
                        if (dp[last][j + 1][k + 1] > tmp) {
                            tmp = dp[last][j + 1][k + 1];
                        }
                        if (dp[last][j][k + 1] > tmp) {
                            tmp = dp[last][j][k + 1];
                        }
                        if (dp[last][j + 1][k] > tmp) {
                            tmp = dp[last][j + 1][k];
                        }
                    }
                    dp[1 - last][j][k] = tmp + a[x1][y1] + a[x2][y2];
                }
            }
        }
        printf("%d
    ", dp[0][1][2] + a[n][n] * 2 + a[1][1]);
        return 0;
    }
    View Code

    单词接龙

    这题思路是想好了,代码实现起来太费时间,手太慢不写了。

    设f[i]表示以第i个单词开始能往后构造的长度。

    从单词s开始可以把26个字母分别加在左边或右边,共52种可能的接龙方式。从这52个f值中选一个最大的加1即可。因为顺序没法确定,所以用dfs来算:for (int i=0;i<n;i++) dfs(i);

    题目中直说单词总长度小于1000000,没说每个单词最大长度,很讨厌。

    每个单词的52种扩展中不一定全在字典里,所以要用一个Trie树来判断。因为单词很长,所以不能一个词一个词的分开存,只能全存在一个数组里然后记录各个端点,用的时候sscanf。

  • 相关阅读:
    hdu2588-GCD-(欧拉函数+分解因子)
    欧拉定理及其扩展定理公式
    hdu2973-YAPTCHA-(欧拉筛+威尔逊定理+前缀和)
    hdu5391-Zball in Tina Town-威尔逊定理(假证明)
    deleted
    deleted
    deleted
    deleted
    deleted
    deleted
  • 原文地址:https://www.cnblogs.com/dramstadt/p/7754837.html
Copyright © 2011-2022 走看看