1. 程式人生 > >[LeetCode] Dota2 Senate 刀塔二參議院

[LeetCode] Dota2 Senate 刀塔二參議院

found with nbsp == sin ise ati note tar

In the world of Dota2, there are two parties: the Radiant and the Dire.

The Dota2 senate consists of senators coming from two parties. Now the senate wants to make a decision about a change in the Dota2 game. The voting for this change is a round-based procedure. In each round, each senator can exercise one

of the two rights:

  1. Ban one senator‘s right:
    A senator can make another senator lose all his rights in this and all the following rounds.
  2. Announce the victory:
    If this senator found the senators who still have rights to vote are all from the same party, he can announce the victory and make the decision about the change in the game.

Given a string representing each senator‘s party belonging. The character ‘R‘ and ‘D‘ represent the Radiant party and the Dire party respectively. Then if there are n senators, the size of the given string will be n.

The round-based procedure starts from the first senator to the last senator in the given order. This procedure will last until the end of voting. All the senators who have lost their rights will be skipped during the procedure.

Suppose every senator is smart enough and will play the best strategy for his own party, you need to predict which party will finally announce the victory and make the change in the Dota2 game. The output should be Radiant or Dire.

Example 1:

Input: "RD"
Output: "Radiant"
Explanation: The first senator comes from Radiant and he can just ban the next senator‘s right in the round 1. 
And the second senator can‘t exercise any rights any more since his right has been banned.
And in the round 2, the first senator can just announce the victory since he is the only guy in the senate who can vote.

Example 2:

Input: "RDD"
Output: "Dire"
Explanation: 
The first senator comes from Radiant and he can just ban the next senator‘s right in the round 1. 
And the second senator can‘t exercise any rights anymore since his right has been banned.
And the third senator comes from Dire and he can ban the first senator‘s right in the round 1.
And in the round 2, the third senator can just announce the victory since he is the only guy in the senate who can vote.

Note:

  1. The length of the given string will in the range [1, 10,000].

該來的總會來!!!自從上次LeetCode拿提莫出題Teemo Attacking後,我就知道刀塔早晚也難逃魔掌,這道題直接就搞起了刀塔二。不過話說如果你是從魔獸3無縫過渡到刀塔,那麽應該熟悉了兩個陣營的叫法,近衛和天災。刀塔二裏面不知道搞什麽鬼,改成了光輝和夢魘,不管了,反正跟這道題的解法沒什麽關系。這道題模擬了刀塔類遊戲開始之前的BP過程,兩個陣營按順序Ban掉對方的英雄,看最後誰剩下來了,就返回哪個陣營。那麽博主能想到的簡單暴力的方法就是先統計所有R和D的個數,然後從頭開始遍歷,如果遇到了R,就掃描之後所有的位置,然後還要掃描R前面的位置,這就要用到數組的環形遍歷的知識了,其實就是坐標對總長度取余,使其不會越界,如果我們找到了下一個D,就將其標記為B,然後對應的計數器cntR自減1。對於D也是同樣處理,我們的while循環的條件是cntR和cntD都要大於0,當有一個等於0了的話,那麽推出循環,返回那個不為0的陣營即可,參見代碼如下:

解法一:

class Solution {
public:
    string predictPartyVictory(string senate) {
        int n = senate.size(), cntR = 0, cntD = 0;
        for (char c : senate) {
            c == R ? ++cntR : ++cntD;
        }
        if (cntR == 0) return "Dire";
        if (cntD == 0) return "Radiant";
        while (cntR > 0 && cntD > 0) {
            for (int i = 0; i < n; ++i) {
                if (senate[i] == R) {
                    for (int j = i + 1; j < i + n; ++j) {
                        if (senate[j % n] == D) {
                            senate[j % n] = B;
                            --cntD;
                            break;
                        }
                    }
                } else if (senate[i] == D) {
                    for (int j = i + 1; j < i + n; ++j) {
                        if (senate[j % n] == R) {
                            senate[j % n] = B;
                            --cntR;
                            break;
                        }
                    }
                }
            }
        }
        return cntR != 0 ? "Radiant" : "Dire";
    }
};

上面的暴力搜索的方法略顯復雜,我們其實有更好的方法來做,我們可以用兩個隊列queue,把各自陣營的位置存入不同的隊列裏面,然後進行循環,每次從兩個隊列各取一個位置出來,看其大小關系,小的那個說明在前面,就可以把後面的那個Ban掉,所以我們要把小的那個位置要加回隊列裏面,但是不能直接加原位置,因為下一輪才能再輪到他來Ban,所以我們要加上一個n,再排入隊列。這樣當某個隊列為空時,推出循環,我們返回不為空的那個陣營,參見代碼如下:

解法二:

class Solution {
public:
    string predictPartyVictory(string senate) {
        int n = senate.size();
        queue<int> q1, q2;
        for (int i = 0; i < n; ++i) {
            (senate[i] == R) ? q1.push(i) : q2.push(i);
        }
        while (!q1.empty() && !q2.empty()) {
            int i = q1.front(); q1.pop();
            int j = q2.front(); q2.pop();
            (i < j) ? q1.push(i + n) : q2.push(j + n);
        }
        return (q1.size() > q2.size()) ? "Radiant" : "Dire";
    }
};

類似題目:

Teemo Attacking

參考資料:

https://discuss.leetcode.com/topic/97671/java-c-very-simple-greedy-solution-with-explanation

LeetCode All in One 題目講解匯總(持續更新中...)

[LeetCode] Dota2 Senate 刀塔二參議院