1. 程式人生 > >ACM-ICPC 2018 徐州賽區網路預賽 C

ACM-ICPC 2018 徐州賽區網路預賽 C

題目連結:點選這裡

解題思路:

對於這麼一個3*3的格子一共就是有八種選擇,那麼題目要求在這八種的選擇的的值的期望中輸出最大的那個.

那麼我們首先就去固定'*'號我們不知道而M知道的點,將他變為已知的值,然後再去暴力dfs列舉'#'號的值,求出這次所有‘*’號固定的情況的八種中的最大期望.最後將最大期望和對固定'*'號方案數求均值就是最後最大值期望了.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = 3e5 + 10;
int n,m,top,siz[10];
int a[25],num1,num2;
double ans1,ans2,ans;
bool vis[20];
int b[8][6] = { 0,0,0,1,0,2,
				1,0,1,1,1,2,
				2,0,2,1,2,2,
				0,0,1,0,2,0,
				0,1,1,1,2,1,
				0,2,1,2,2,2,
				0,0,1,1,2,2,
				0,2,1,1,2,0};
void init(){
	memset(a, 0, sizeof(a));
	a[6] = 10000;
	a[7] = 36;
	a[8] = 720;
	a[9] = 360;
	a[10] = 80;
	a[11] = 252;
	a[12] = 108;
	a[13] = 72;
	a[14] = 54;
	a[15] = 180;
	a[16] = 72;
	a[17] = 180;
	a[18] = 119;
	a[19] = 36;
	a[20] = 360;
	a[21] = 1080;
	a[22] = 144;
	a[23] = 1800;
	a[24] = 3600;
}
char str[10][10];
void dfs2(int *p,int x,int c)
{
	if(c==3){
		num2++;
		ans2 += a[str[p[0]][p[1]]+str[p[2]][p[3]]+str[p[4]][p[5]]-3*'0'];
		return ;
	}
	if(str[p[x]][p[x+1]]=='#')
	for(int i=1;i<=9;i++){
		if(!vis[i]){
			vis[i] = 1;
			str[p[x]][p[x+1]] = i + '0';
			dfs2(p,x+2,c+1);
			vis[i] = 0;
			str[p[x]][p[x+1]] = '#';			
		}
	}
	else dfs2(p,x+2,c+1);
}
void dfs1(int x,int y,int c)
{
	if(!c){
		num1++,ans1 = 0;
		for(int i=0;i<8;i++){
			ans2 = num2 = 0;
			dfs2(b[i],0,0);
			ans1 = max(ans1,ans2/num2);
		}
		ans += ans1;
		return ;
	}
	if(str[x][y]=='*')
	for(int k=1;k<=9;k++){
		if(!vis[k]){
			str[x][y] = k + '0';
			vis[k] = 1;
			dfs1(y==2?x+1:x,y==2?0:y+1,c-1);
			vis[k] = 0;
			str[x][y] = '*';
		}
	}
	else dfs1(y==2?x+1:x,y==2?0:y+1,c);
}
int main()
{
	init();
	scanf("%d",&n);
	while(n--)
	{
		memset(vis,0,sizeof(vis));
		for(int i=0;i<3;i++) scanf("%s",str[i]);
		int cnt = 0;
		num1 = num2 = 0;
		ans = ans1 = ans2 = 0;
		for(int i=0;i<3;i++){
			for(int j=0;j<3;j++){
				if(str[i][j]=='*') cnt++;
				else vis[str[i][j]-'0'] = 1;
			}
		}
		dfs1(0,0,cnt);
		//cout << ans << " " << num1 << endl; 
		printf("%.8lf\n",1.0*ans/num1);
	}
	return 0;
}