BZOJ 3901 棋盘游戏(可能是网络流但我只会暴力)

本文探讨了一种在特定游戏环境中,通过策略性地操作棋盘格子,以达到最大数值和的方法。通过分析棋盘的特性,特别是对于中心点及其周边格子的操作规律,提出了一种有效的搜索算法来确定最优策略。

题面:

在一个游戏中,给定一个 n n 的正方形棋盘,每个格子内有一个整数。保证 n 为奇数。令
x = (n+1)/2 。你可以进行下述操作任意次:每次选择一个 x * x 的子棋盘,将其中所有数乘上-1。
求经过一系列操作后棋盘上所有数之和的最大值。

从x突破。
首先发现对于(x,x)每一个操作都要改它,它的正负性为操作次数的奇偶性。
然后发现对于(x,a)和 (x,a+x) (a<x) 每一个操作都恰好只操作其中一个。
设一个点操作次数的奇偶性为ta,bt_{a,b}ta,b
然后就发现tx,a⊕tx,a+x=tx,xt_{x,a} \oplus t_{x,a+x} = t_{x,x}tx,atx,a+x=tx,x
反过来:tx,a⊕tx,x=tx,a+xt_{x,a} \oplus t_{x,x} = t_{x,a+x}tx,atx,x=tx,a+x
同理:ta,b⊕ta,x=ta,b+xt_{a,b} \oplus t_{a,x} = t_{a,b+x}ta,bta,x=ta,b+x
ta,b⊕tx,b=ta+x,bt_{a,b} \oplus t_{x,b} = t_{a+x,b}ta,btx,b=ta+x,b
那么可以证明满足这样所有条件的t可以被操作出来。
那么我们只需要看t。
实际上只需要左上角x∗xx*xxxttt就可以推出全部的ttt
然后左下,右上的点权可以作为用二元关系表示。
但是右下:4元关系???
这方程我解出来无解。。。。。。
还是别玩网络流了。

n&lt;=33n&lt;=33n<=33
考虑搜。
a[x][1] to a[x][x]a[x][1] \ to\ a[x][x]a[x][1] to a[x][x]
然后把a[x]a[x]a[x]全算出来,然后不难发现其实每一行的值是独立的。也就是说ta,bt_{a,b}ta,b选什么值都不会对于tk,p(k!=a and k!=a+x)t_{k,p} (k!=a \ and\ k!=a + x)tk,p(k!=a and k!=a+x)造成任何限制。
那么对于每一行贪心。
然后ta,bt_{a,b}ta,b只会影响ta+x,b,ta,b+x,ta+x,b+xt_{a+x,b},t_{a,b+x},t_{a+x,b+x}ta+x,b,ta,b+x,ta+x,b+x
再来一个贪心即可。

O(n2217)O(n^22^{17})O(n2217)

AC Code:

#include<bits/stdc++.h>
#define maxn 35
using namespace std;

int n,a[maxn][maxn],x,t[maxn][maxn];
int ans = -0x3f3f3f3f;

int ser(int X,int Y,int rval,int nval)
{
	return nval * a[X][Y] + nval * rval * a[X][Y+x]
		+ nval * t[x][Y] * a[X+x][Y] + nval * rval * t[x][Y] * t[x][x] * a[X+x][Y+x];
}

int calc(int pos,int val)
{
	int ret = val * a[pos][x] + val * t[x][x] * a[pos+x][x];
	for(int i=1;i<x;i++)
		ret+=max(ser(pos,i,val,1),ser(pos,i,val,-1));
	return ret;
}

void solve()
{
	int ret = 0;
	for(int i=x+1;i<=n;i++) t[x][i] = t[x][i-x] * t[x][x];
	for(int i=1;i<=n;i++) ret += t[x][i] * a[x][i];
	for(int i=1;i<x;i++)
		ret += max(calc(i,-1),calc(i,1));
	ans = max(ans , ret);
}

void dfs(int now)
{
	if(now == x+1){solve();return;}
	t[x][now]=-1,dfs(now+1);
	t[x][now]=1,dfs(now+1);
}

int main()
{
	scanf("%d",&n),x=(n+1)/2;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
	dfs(1);
	printf("%d\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值