ccf csp-201803-4-棋局评估(回溯)

原试题点击此处

  • 最优策略(难点):对于alice而言,他下棋的最优策略是让棋盘最后下完得分的值越高越好,反之,bob的最优策略就是让得分越低越好。
  • 尝试所有空位置,回溯求解。

代码如下

#include<iostream>
#include<cmath>
#include<climits>
using namespace std;
int a[3][3];
bool isWin(int k){
	for(int i = 0; i < 3; i++){
		if(a[i][0]==k&&a[i][1]==k&&a[i][2]==k) return true;
		if(a[0][i]==k&&a[1][i]==k&&a[2][i]==k) return true;
	}
	if(a[0][0]==k&&a[1][1]==k&&a[2][2]==k) return true;
	if(a[2][0]==k&&a[1][1]==k&&a[0][2]==k) return true;
	return false;
}
int dfs(int k){
	int t = 0;
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 3; j++){
			if(a[i][j]==0) t++;
		}
	}
	//递归出口 
	if(k==1&&isWin(2)) return -(t+1);
	if(k==2&&isWin(1)) return (t+1);
	if(t==0) return 0; 
	int maxx = -INT_MAX,minn=INT_MAX; 
	for(int i = 0; i < 3; i++){
		for(int j = 0; j < 3; j++){
			if(a[i][j]==0){
				a[i][j] = k;//尝试下棋 
				if(k==1) maxx = max(maxx,dfs(2));
				if(k==2) minn = min(minn, dfs(1));
				a[i][j] = 0;
			}
		}
	}
	//所有空格都模拟完后 
	if(k==1) return maxx;
	if(k==2) return minn;
}
int main()
{
	int n,ans;
	scanf("%d", &n);
	for(int num = 0; num < n; num++){
		for(int i = 0; i < 3; i++){
			for(int j = 0; j < 3; j++){
				scanf("%d", &a[i][j]);
			}
		}
		ans = dfs(1);//Alice先下棋 
		cout<<ans<<endl;
	}
	return 0;
}
发布了118 篇原创文章 · 获赞 755 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_42437577/article/details/104352294