题目
错误思路
只管当前回合能够凑成移出的石子不是3的倍数。
代码
class Solution {
public:
bool stoneGameIX(vector<int>& stones) {
int n=stones.size(),out=0,round=0;
vector<bool> vis(n);
while(++round<=n){
bool flag=false;
for(int i=0;i<n;i++){
if(vis[i]==false && (stones[i]+out)%3!=0){
out+=stones[i];
vis[i]=true;
flag=true;
break;
}
}
if(!flag) return (round&1)==0;
}
return false;
}
};
正确思路
A只有一种获胜方式,就是在B选石子时凑成3的倍数。
把所有石子分成三类,除以3余数分别为0、1、2,记为s=0、1、2。当前移出的石子个数也有余0、1、2三种情况,记为x=1、2、3.
s=0的个数是偶数时,相当于换手两次,不对局面造成任何改变。
如果s=0的个数为偶数,s=1或s=2的个数为0,等到第三次选择时就会凑成3的倍数,B必胜。
如果s=0的个数为偶数,s=1和s=2的个数都不为0,只需要A先手选择较少数量的那一种石子,B都必须和A选择相同的石子,但A后来可以选择数量多的石子,最后B选择时会先凑成3的倍数,A必胜。
如果s=0的个数为奇数,s=1和s=2的数量差超过2,A的先手优势可以选择数量多类型的石子,能够抵消B换手的机会,A必胜。
如果s=0的个数为奇数,s=1和s=2的数量差不超过2,不管A第一轮选什么,B第一轮选了s=0的话,A第二轮就只能选和第一轮一样的,这样就变成了B先手,s=1和s=2的数量差超过2的情况,A会先遇到只能凑成3的倍数或石子被取完的情况,所以B必胜。
代码
class Solution {
public:
bool stoneGameIX(vector<int>& stones) {
vector<int> cnt(3);
for(int stone:stones)
cnt[stone%3]++;
return (cnt[0]&1)==0 ? (cnt[1] != 0 && cnt[2] != 0) : (abs(cnt[1]-cnt[2])>2);
}
};