#C241116A. 棋盘游戏


#C241116A. 棋盘游戏

标签(Label)

  • 观察+分析

网址(Website)

题目详情 - 棋盘游戏 - Super

题解 - 棋盘游戏 - Super

题目(Problem)

样例

输入数据 1

2
3
1 1 1
1 1 1
1 1 1
5
8 5 2 8 3
5 6 9 7 3
7 8 9 1 4
8 9 4 5 5
2 8 6 9 3

输出数据 1

1
5

题解(Solution)

看到这道题的 $\sum n^2 $ 足足有 $5\times 10^5$ ,就开始想一堆带 $\log$ 的做法 ,总觉得有一些性质,但是又没有提取出来。

我们设 $mid=\frac{n}{2}+1$ 。不考虑复杂度,找一下这个题的规律。

矩阵往往是四个角最特殊。发现每次覆盖至少覆盖 $\frac{1}{4}$ 的范围,我们想要覆盖整个范围,就需要把四个角都给覆盖,发现对于 $(1,1)$ 位置,能覆盖到这个位置的矩阵的中心 $(x,y)$ 一定满足 $x\in[1,mid]\land y\in[1,mid]$ ,其他的角同理。容易发现当 $(1,1)$ 这个位置被覆盖之后,矩阵的 $(x,y)\vert x\in[1,mid]\land y\in[1,mid]$ 的点一定也会被覆盖,对于 $(x,y)\vert x\in[1,mid-1]\land y\in[1,mid-1]$ ,这些点只能覆盖 $(1,1)$ 这个点,对于 $(x,mid)$ 或 $(mid,y)$ ,它们至少可以覆盖两个角,特别的,对于 $(mid,mid)$ ,它可以直接覆盖所有位置。

观察到这些性质之后,我们就是要在四个角里面分别找到最小值来覆盖对应的角,对于在中轴上的点,它可以完成自己能覆盖的两个角的操作,因此就对这对应的两个角取 $\min$ ,最后拼接出来能覆盖四个角的方案,然后与 $(mid,mid)$ 一个点操作的方案取 $\min$ 就好了。

时间复杂度 $O(n^2)$ 。

出题者题解![](https://wolfdeer62456.github.io/2024/11/16/C241116A-%E6%A3%8B%E7%9B%98%E6%B8%B8%E6%88%8F/3.png)

代码(Code)

#include<bits/stdc++.h>
#include<vector>
#include<queue>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
using namespace std;
#define P pair<int,int> 
#define int long long
#define x first
#define y second
inline int rd(){
	char c;bool f=false;while(!isdigit(c=getchar()))f=c=='-';int x=c^48;
	while(isdigit(c=getchar())){x=(((x<<2)+x)<<1)+(c^48);}return f?-x:x;
}const int inf = 0x3f3f3f3f3f3f3f3f;
const int N = 505;
const int S = 501234;
bool ST;

priority_queue<pair<P,P>> q;
int n,half,ans,a[N][N];
int c[4][4],s[6],md;

void Solve(){
	memset(c, 0x3f, sizeof c);
	memset(s, 0x3f, sizeof s);
	md = ans = inf;
	
	n=rd(),half=n/2+1;
	For(i,1,n) For(j,1,n){
		int x=rd();
		if(i^half && j^half) c[i/half][j/half] = min(c[i/half][j/half], x);else
		if(i==half && j^half){
			if(j<half) s[1] = min(s[1], x), c[0][0] = min(c[0][0], x), c[1][0] = min(c[1][0], x);
			else s[3] = min(s[3], x), c[0][1] = min(c[0][1], x), c[1][1] = min(c[1][1], x);
		}else
		if(i^half && j==half){
			if(i<half) s[4] = min(s[4], x), c[0][0] = min(c[0][0], x), c[0][1] = min(c[0][1], x);
			else s[2] = min(s[2], x), c[1][0] = min(c[1][0], x), c[1][1] = min(c[1][1], x);
		}else{
			assert(i==half && j==half);
			md = min(md, x);
		}
	}
	s[1] = min(s[1], c[0][0]+c[1][0]);
	s[2] = min(s[2], c[1][0]+c[1][1]);
	s[3] = min(s[3], c[0][1]+c[1][1]);
	s[4] = min(s[4], c[0][0]+c[0][1]);
	ans = min({md, s[1]+s[3], s[2]+s[4]});
	printf("%lld\n", ans);
}

bool ED;
signed main(){
	cerr<<abs(&ST-&ED)/1024./1024.<<"MB\n";
	freopen("distorted.in","r",stdin);
	freopen("distorted.out","w",stdout);
	int Tt=rd();double Tim=clock();
	while(Tt--) Solve();
	return cerr<<"TIME:"<<(clock()-Tim)/CLOCKS_PER_SEC,0;
}

文章作者: WolfDeer
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WolfDeer !
  目录