649.Dota2 参议院

1,550 阅读2分钟

题目:
Dota2 的世界里有两个阵营:Radiant(天辉)和 Dire(夜魇)

Dota2 参议院由来自两派的参议员组成。现在参议院希望对一个 Dota2 游戏里的改变作出决定。他们以一个基于轮为过程的投票进行。在每一轮中,每一位参议员都可以行使两项权利中的项:

  1. 禁止一名参议员的权利

    参议员可以让另一位参议员在这一轮和随后的几轮中丧失所有的权利

  2. 宣布胜利

          如果参议员发现有权利投票的参议员都是同一个阵营的,他可以宣布胜利并决定在游戏中的有关变化。给定一个字符串代表每个参议员的阵营。字母 “R” 和 “D” 分别代表了 Radiant(天辉)和 Dire(夜魇)。然后,如果有 n 个参议员,给定字符串的大小将是 n

以轮为基础的过程从给定顺序的第一个参议员开始到最后一个参议员结束。这一过程将持续到投票结束。所有失去权利的参议员将在过程中被跳过。

假设每一位参议员都足够聪明,会为自己的政党做出最好的策略,你需要预测哪一方最终会宣布胜利并在 Dota2 游戏中决定改变。输出应该是 Radiant 或 Dire

算法: 方法一:贪心暴力法(待优化):

  • 82/82 cases passed (336 ms)
  • Your runtime beats 5.36 % of golang submissions
  • Your memory usage beats 39.29 % of golang submissions (3.1 MB)
func predictPartyVictory(senate string) string {
	voteState := make([]int, len(senate))
	radiantVote := 0
	direVoteCount := 0
	for i := range senate {
		if senate[i] == byte('R') {
			radiantVote ++
		} else if senate[i] == byte('D') {
			direVoteCount ++
		}
		voteState[i] = 1
	}

	k := 0
	length := len(senate)
	for {
		// 能否宣布胜利?
		// 不能,沉默一名对面玩家
		if senate[k] == byte('R') && voteState[k] > 0 {
			if direVoteCount == 0 {
				return "Radiant"
			} else {
				// 沉默对面玩家
				slience(voteState, senate, k, byte('D'))
				direVoteCount --
			}
			
		}
		// fmt.Println(voteState)
		if senate[k] == byte('D') && voteState[k] > 0 {
			if radiantVote == 0 {
				return "Dire"
			} else {
				// 沉默对面玩家
				slience(voteState, senate, k, byte('R'))
				radiantVote --
			}
		}


		k = (k + 1) % length
	}
	
	return ""
}

// 从index开始沉默一名反对党成员
func slience(voteState []int, senate string, index int, byt byte)  bool {
	for i := (index + 1) % len(voteState); i != index; i = (i + 1) % len(voteState) {
		if voteState[i] == 1 && senate[i] == byt {
			voteState[i] = 0
			return true
		}
	}
	return false
}