1. 程式人生 > >【CCF 201803-4】棋局評估(對抗搜尋)

【CCF 201803-4】棋局評估(對抗搜尋)

思路

①當Alice下的時候,我們嘗試所有可能的下法,並找到所有下法中使結果最大的一個

Bob下的時候,我們嘗試所有可能的下法,並找到所有下法中使結果最小的一個

②輪流執子,直到雙方有人勝利或棋盤填滿

 蒟蒻我還是不能很好的表達出意思來...QAQ

C++滿分程式碼(帶註釋)

#include <iostream>
using namespace std;

const int inf = 1e8;
int chess[3][3];

inline int Score()	//返回棋局的得分,若未結束則返回inf 
{
	int blank = 0;		//空格數 
	for(int i=0; i<3; ++i)
		for(int j=0; j<3; ++j)
			if(chess[i][j] == 0) ++blank;
	int flag = (blank & 1 ? -1 : 1);	//空格數為偶數,說明走了奇數步,這時Bob可能要贏了,故flag=-1 

	for(int i=0; i<3; ++i)
		if(chess[i][0]==chess[i][1] && chess[i][1]==chess[i][2] && chess[i][0]) return flag*(blank+1);
	for(int j=0; j<3; ++j)
		if(chess[0][j]==chess[1][j] && chess[1][j]==chess[2][j] && chess[2][j]) return flag*(blank+1);
	if(chess[0][0]==chess[1][1] && chess[1][1]==chess[2][2] && chess[2][2]) return flag*(blank+1);
	if(chess[2][0]==chess[1][1] && chess[1][1]==chess[0][2] && chess[0][2]) return flag*(blank+1);

	if(blank == 0) return 0;		//如果沒人贏,又下滿了,則為平局 
	return inf;
}

inline int search(int a)	//下面以Alice為例進行說明,Bob在(*)處正好相反 
{
	int score = Score();
	if(score != inf) return score;	//若結束,返回分數 

	int optimal = (a == 1 ? -inf : inf), tmp;	//optimal初始化為-inf,Alice要使optimal達到最大 (*)
	for(int i=0; i<3; ++i)
		for(int j=0; j<3; ++j)
		{
			if(chess[i][j] == 0)		//對所有空格子進行嘗試
			{
				chess[i][j] = a;
				tmp = (a == 1 ? search(2) : search(1));	//Alice下完Bob下  (*)
				if(a == 1) optimal = max(tmp, optimal);	//optimal取較大者 (*)
				else optimal = min(tmp, optimal);
				chess[i][j] = 0;		//嘗試之後記得復原 
			}
		}

	return optimal;
}

int main()
{
	ios::sync_with_stdio(false);

	int t;
	cin>>t;
	while(t--)
	{
		for(int i=0; i<3; ++i)		//輸入 
			for(int j=0; j<3; ++j)
				cin>>chess[i][j];
		cout<<search(1)<<"\n";		//輸出 
	}

	return 0;
}