• HDU4536 XCOM Enemy Unknown 枚举


    题意:有N个国家,每个国家属于一个洲,现在有人要来攻击一些国家,每次攻击选择来自三个不同洲的国家,我们能够选择去保护一个国家,被保护的国家恐惧值-2,其余两个国家恐惧值+2,和这两个国家在一个洲的国家恐惧值+1。

    分析:由于超过5点恐惧值就以及超过极限了,而每次攻击又会带来其余两个洲恐惧值的增加,因此最多在不超过10天的情况下将会出现有国家超过5点恐惧值。

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int N, M, K;
    char val[20], con[20];
    char kill[105][5];
    
    bool fail() {
        for (int i = 0; i < N; ++i) {
            if (val[i] > 5) return true;
        }
        return false;
    }
    
    inline void fix(char &x) {
        if (x < 1) x = 1;
    }
    
    void modify(int x, int p) { // x天,支援第kill[x][i]个国家
        char a = kill[x][p], b = kill[x][(p+1)%3], c = kill[x][(p+2)%3];
        val[a] -= 2, fix(val[a]);
        val[b] += 2, val[c] += 2;
        for (int i = 0; i < N; ++i) {
            if (con[i] == con[a]) continue;
            if (i == b || i == c) continue;
            if (con[i] == con[b]) val[i] += 1;
            if (con[i] == con[c]) val[i] += 1;
        }
    }
    
    bool dfs(int x, int end) { // return 1 表示存在一种方案使得所有国家安然无恙
    //    printf("x = %d\n", x);
        if (fail()) {  // 中间任何一天有国家超过了5点恐慌说明该种方案失败
            return false;
        }
        if (x == end+1) { // 熬到了第end+1天,说明有一种方案平安度过了前面end天 
            return true;
        }
        char cpy[20];
        memcpy(cpy, val, sizeof (val));
        for (int i = 0; i < 3; ++i) {
            // 第x天,支援第kill[x][i]个国家
            modify(x, i);
            if (dfs(x+1, end)) {
                return true;
            }
            memcpy(val, cpy, sizeof (cpy));
        }
        return false;
    }
    
    int main() {
        int T;
        scanf("%d", &T);
        for (int ca = 1; ca <= T; ++ca) {
            scanf("%d %d %d", &N, &M, &K);
            for (int i = 0; i < N; ++i) {
                scanf("%d", &con[i]); // 说明该国家属于哪一个洲
            }
            for (int i = 0; i < N; ++i) {
                scanf("%d", &val[i]);    
            }
            for (int i = 0; i < K; ++i) {
                for (int j = 0; j < 3; ++j) {
                    scanf("%d", &kill[i][j]);
                }
            }
            int ans = K;
            char cpy[20]; // 由于有一个最小不低于1的限制,因此不能在原来基础上进行恢复 
            for (int i = 0; i < K; ++i) {
                memcpy(cpy, val, sizeof (val)); // 这里没有记录原来的值,导致错了很久 
                if (!dfs(0, i)) {
                    ans = i;
                    break;
                }
                memcpy(val, cpy, sizeof (cpy));
            }
            printf("Case #%d: %d\n", ca, ans);
        }
        return 0;
    }

    BFS版本:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int N, M, K, ans;
    char val[20], con[20];
    char kill[105][5];
    
    bool fail(char val[]) {
        for (int i = 0; i < N; ++i) {
            if (val[i] > 5) return true;
        }
        return false;
    }
    
    inline void fix(char &x) {
        if (x < 1) x = 1;
    }
    
    void modify(char val[], int x, int p) { // x天,支援第kill[x][i]个国家
        int a = kill[x][p], b = kill[x][(p+1)%3], c = kill[x][(p+2)%3];
        val[a] -= 2, fix(val[a]);
        val[b] += 2, val[c] += 2;
        for (int i = 0; i < N; ++i) {
            if (con[i] == con[a]) continue;
            if (i == b || i == c) continue;
            if (con[i] == con[b]) val[i] += 1;
            if (con[i] == con[c]) val[i] += 1;
        }
    }
    
    struct Que {
        char val[20];
        char day;
    }q[1000000], pos;
    
    int front, tail;
    
    void bfs() {
        front = tail = 0;
        q[tail].day = 0;
        memcpy(q[tail++].val, val, sizeof (val));
        while (front != tail) {
            pos = q[front++];
            ans = pos.day;
            if (pos.day >= K) continue;
            for (int i = 0; i < 3; ++i) {
                q[tail] = pos;
                modify(q[tail].val, pos.day, i);
                if (!fail(q[tail].val)) {
                    q[tail++].day = pos.day + 1;    
                }
            }
        }
    }
    
    int main() {
        int T;
        scanf("%d", &T);
        for (int ca = 1; ca <= T; ++ca) {
            scanf("%d %d %d", &N, &M, &K);
            for (int i = 0; i < N; ++i) {
                scanf("%d", &con[i]); // 说明该国家属于哪一个洲
            }
            for (int i = 0; i < N; ++i) {
                scanf("%d", &val[i]);
            }
            for (int i = 0; i < K; ++i) {
                for (int j = 0; j < 3; ++j) {
                    scanf("%d", &kill[i][j]);
                }
            }
            bfs();
            printf("Case #%d: %d\n", ca, ans);
        }
        return 0;
    }
  • 相关阅读:
    3、总结
    三分及小例题
    约瑟夫问题的推导
    对于联通块的处理
    扩展欧几里得与二元不定方程
    js 阻止事件捕获
    原生xhr发送JSON
    $timeout
    Angularjs Ng_repeat中实现复选框选中并显示不同的样式
    为什么用Object.prototype.toString.call(obj)检测对象类型?
  • 原文地址:https://www.cnblogs.com/Lyush/p/2992450.html
Copyright © 2020-2023  润新知