HDU-4536 XCOM Enemy Unknown 枚举

本文探讨了如何在特定环境下,通过算法选择保护国家,以管理国家间的恐惧值,确保在不超过10天内避免任何国家恐惧值超过5点的情况发生。详细介绍了算法逻辑与实现过程,包括恐惧值变化的数学模型、DFS与BFS求解策略及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:有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;
}

 

转载于:https://www.cnblogs.com/Lyush/archive/2013/03/31/2992450.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值