Krito的討伐(bfs加上優先隊列)

Description

Krito終於幹掉了99層的boss,來到了第100層。第100層可以表示成一顆樹,這棵樹有n個節點(編號從0到n-1),樹上每一個節點可能有很多隻怪物。 Krito現在在0號節點,現在它想要區清除這一層所有的怪物。他現在有atk大小的攻擊力。只有當你的攻擊力大於這隻怪物的防禦力時,你纔可以打敗他,同時每打敗只怪物,你會獲得一定的攻擊力加成。一個節點可能存在着不止一隻怪獸,你要打敗這個節點的所有怪物才能可以從這個節點通過,請問他能不能完成這個任務?注意:不要求一次性殺光一個節點裏面的所有怪物。

Input

第1行:一個數T,表示有T個測試樣例(0<=T<=50) ,接下來有T個測試樣例

對於每一個測試樣例:

第1行:兩個整數n,m表示這棵樹有n個節點,m只怪獸(0<=n<=1000 ,0<=m <=100)

第2至n-1行: 兩個整數u,v表示編號爲u,v之間的節點有一條無向邊,題目保證不會成環。(0<=u,v<n , u!=v)

第3行: 一個整數atk,表示Krito的初始化攻擊力(0<=atk<=100)

第4至3+m行:兩個整數id,def,add_atk,表示在編號爲id的點上,有一隻防禦力爲def的怪物,打敗後可以增加add_atk點的攻擊力。(0<=add_atk,def<=100)

Output

對於每一個測試樣例,如果Krito能夠清除所有的怪物,則輸出“Oh yes.” 否則,輸出“Good Good Study,Day Day Up.”

Sample Input

15 20 10 22 32 4113 10 21 11 0

Sample Output

Oh yes.

利用有限隊列可以解決此問題
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <cstdio>

using namespace std;

const int MAX_N = 1009;

int n, m, atk;
struct Node
{
    int id;
    int def;
    int add;
    // 自定義優先隊列的排列規則
    friend bool operator<(Node a, Node b)
    {
        return a.def > b.def;
    }
};
int g[MAX_N][MAX_N];    // 鄰接矩陣模擬樹
int cnt[MAX_N];         // 每個節點上的怪物
vector<Node> v[MAX_N];  // 每個節點上的全部怪物信息
bool visit[MAX_N];      // 標記該點是否訪問過

// 初始化
void init()
{
    memset(g, 0, sizeof(g));
    memset(cnt, 0, sizeof(cnt));
    memset(visit, false, sizeof(visit));
    for(int i = 0; i < MAX_N; i++)
        v[i].clear();
}

// bfs+優先隊列
bool bfs()
{
    priority_queue<Node> q;
    for(int i = 0; i < v[0].size(); i++)    // 將根節點信息加入到隊列
        q.push(v[0][i]);

    if(cnt[0] == 0)     // 如果根節點沒有怪物,則把def標記爲-1
    {
        Node t = {0, -1, 0};
        q.push(t);
    }
    visit[0] = true;        // 標記根節點已被訪問
    while(!q.empty())
    {
        Node t = q.top();
        q.pop();
        if(t.def == -1)
        {
            for(int i = 0; i < n; i++)
            {
                if(!visit[i] && g[t.id][i] == 1)    // 遍歷與該節點連通且未被訪問的節點
                {
                    visit[i] = true;    // 標記節點已被訪問
                    for(int j = 0; j < cnt[i]; j++)
                        q.push(v[i][j]);    // 這個節點上的怪物信息都加入優先隊列
                    if(cnt[i] == 0)
                    {
                        Node x = {i, -1, 0};    // 如果該點沒有怪物,將def標記爲-1
                        q.push(x);
                    }
                }
            }

            continue;
        }

        if(atk > t.def)
        {
            atk += t.add;
            if(--cnt[t.id] == 0)
            {
                t.def = -1;
                q.push(t);
            }
        }
        else
            return false;
    }
    return true;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        init();
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n - 1; i++)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            g[a][b] = g[b][a] = 1;     // 使用鄰接矩陣表示樹
        }

        scanf("%d", &atk);

        for(int i = 0; i < m; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            Node temp = {a, b, c};
            v[a].push_back(temp);
            cnt[a]++;
        }

        if(bfs())
            printf("Oh yes.\n");
        else
            printf("Good Good Study,Day Day Up.\n");
    }

    return 0;
}



發佈了42 篇原創文章 · 獲贊 15 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章