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

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88415819

题面:

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

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

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

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

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);
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/88415819