版权声明:本文为博主原创文章,未经博主允许必须转载。 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可以被操作出来。
那么我们只需要看t。
实际上只需要左上角
的
就可以推出全部的
然后左下,右上的点权可以作为用二元关系表示。
但是右下:4元关系???
这方程我解出来无解。。。。。。
还是别玩网络流了。
考虑搜。
搜
然后把
全算出来,然后不难发现其实每一行的值是独立的。也就是说
选什么值都不会对于
造成任何限制。
那么对于每一行贪心。
然后
只会影响
再来一个贪心即可。
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);
}