71 lines
3.0 KiB
Markdown
71 lines
3.0 KiB
Markdown
|
||
## 思路
|
||
|
||
这道题 题意太绕了,我举一个更形象的例子给大家捋顺一下。
|
||
|
||
例如输入"RRDDD",执行过程应该是什么样呢?
|
||
|
||
* 第一轮:senate[0]的R消灭senate[2]的D,senate[1]的R消灭senate[3]的D,senate[4]的D消灭senate[0]的R,此时剩下"RD",第一轮结束!
|
||
* 第二轮:senate[0]的R消灭senate[1]的D,第二轮结束
|
||
* 第三轮:只有R了,R胜利
|
||
|
||
估计不少同学都困惑,R和D数量相同怎么办,究竟谁赢,**其实这是一个持续消灭的过程!** 即:如果同时存在R和D就继续进行下一轮消灭,轮数直到只剩下R或者D为止!
|
||
|
||
那么每一轮消灭的策略应该是什么呢?
|
||
|
||
例如:RDDRD
|
||
|
||
第一轮:senate[0]的R消灭senate[1]的D,那么senate[2]的D,是消灭senate[0]的R还是消灭senate[3]的R呢?
|
||
|
||
当然是消灭senate[3]的R,因为当轮到这个R的时候,它可以消灭senate[4]的D。
|
||
|
||
**所以消灭的策略是,尽量消灭自己后面的对手,因为前面的对手已经使用过权利了,而后序的对手依然可以使用权利消灭自己的同伴!**
|
||
|
||
那么局部最优:有一次权利机会,就消灭自己后面的对手。全局最优:为自己的阵营赢取最大利益。
|
||
|
||
局部最优可以退出全局最优,举不出反例,那么试试贪心。
|
||
|
||
如果对贪心算法理论基础还不了解的话,可以看看这篇:[关于贪心算法,你该了解这些!](https://mp.weixin.qq.com/s/O935TaoHE9Eexwe_vSbRAg) ,相信看完之后对贪心就有基本的了解了。
|
||
|
||
## 代码实现
|
||
|
||
实现代码,在每一轮循环的过程中,去过模拟优先消灭身后的对手,其实是比较麻烦的。
|
||
|
||
这里有一个技巧,就是用一个变量记录当前参议员之前有几个敌对对手了,进而判断自己是否被消灭了。这个变量我用flag来表示。
|
||
|
||
C++代码如下:
|
||
|
||
|
||
```
|
||
class Solution {
|
||
public:
|
||
string predictPartyVictory(string senate) {
|
||
// R = true表示本轮循环结束后,字符串里依然有R。D同理
|
||
bool R = true, D = true;
|
||
// 当flag大于0时,R在D前出现,R可以消灭D。当flag小于0时,D在R前出现,D可以消灭R
|
||
int flag = 0;
|
||
while (R && D) { // 一旦R或者D为false,就结束循环,说明本轮结束后只剩下R或者D了
|
||
R = false;
|
||
D = false;
|
||
for (int i = 0; i < senate.size(); i++) {
|
||
if (senate[i] == 'R') {
|
||
if (flag < 0) senate[i] = 0; // 消灭R,R此时为false
|
||
else R = true; // 如果没被消灭,本轮循环结束有R
|
||
flag++;
|
||
}
|
||
if (senate[i] == 'D') {
|
||
if (flag > 0) senate[i] = 0;
|
||
else D = true;
|
||
flag--;
|
||
}
|
||
}
|
||
}
|
||
// 循环结束之后,R和D只能有一个为true
|
||
return R == true ? "Radiant" : "Dire";
|
||
}
|
||
};
|
||
```
|
||
|
||
**如果感觉题解对你有帮助,不要吝啬给一个👍吧!**
|
||
|