法一:朴素法,也是看完题后最先想到的,从头开始对于每位议员i,从i的后面开始循环找到i的首个未被禁言的敌人j,并把它的rec[j]
置为0,表示被禁言;只有rec[i]!=0
的时候,才说明i未被禁言,才能进入循环发挥i的权利;如果某次循环中找不到i的敌人了,那么说明i阵营胜利;
string predictPartyVictory(string senate)
{
int len = senate.size();
vector<bool> rec(len, 1);
while (true)
{
for (int i = 0; i < len; i++)
{
//如果i没有被禁言
if (rec[i])
{
char target = senate[i] == 'R' ? 'D' : 'R';
int num = 0;
//从i的后面开始找i的首个未被禁言的敌人,将他禁言
for (int j = i + 1; num < len; num++)
{
if (j == len)
j = 0;
if (rec[j] && senate[j] == target)
{
rec[j] = 0;
break;
}
j++;
}
//找了一圈都没找到i的敌人,说明i阵营胜利
if (num == len)
return senate[i] == 'R' ? "Radiant" : "Dire";
}
}
}
int i = 0;
while (!rec[i])
i++;
return senate[i] == 'R' ? "Radiant" : "Dire";
}
方法二:贪心法,就是当遍历到R的时候,不要马上去找D把它淘汰掉,而是用一个变量记着,等遍历到D的时候再把它淘汰掉;
string predictPartyVictory(string senate)
{
int len = senate.size();
int person = 0; //person>0说明存了一个D淘汰R的权限,person<0说明存了一个R淘汰D的权限;
bool R = true, D = true;
//只要senate中R和D阵营都还有人,那就得继续淘汰
while (R && D)
{
R = false;
D = false;
for (int i = 0; i < len; i++)
{
if (senate[i] == 'D')
{
D = true;
if (person < 0) //里面有R淘汰D的权限,这个D被淘汰
senate[i] = '0';
person++;
}
else if (senate[i] == 'R')
{
R = true;
if (person > 0) //里面有D淘汰R的权限,这个R被淘汰
senate[i] = '0';
person--;
}
}
}
return person > 0 ? "Dire" : "Radiant";
}