Loading

题解:P6469 [COCI2008-2009#6] NERED

[COCI2008-2009#6] NERED

思路

看到 \(n\le100\) 就知道可以随便折腾。

由题意得,所有格子的权值和为 \(m\),那么变换后的矩形的面积也就是 \(m\)

对于一个面积为 \(m\) 的矩形,将其变为合法矩形所需要的代价为范围内权值为 \(0\) 的点的个数,直接枚举所有面积为 \(m\) 的矩形即可。

优化

考虑到要多次求不定区间内权值为 \(0\) 的点的个数,可以使用前缀和优化,这里不再过多赘述。

未优化的时间复杂度约为 \(O\left(n^2 \times m^{3/2}\right)\),优化后约为 \(O\left(n^2 \times \sqrt{m}\right)\)

因为数据太小,优化的效果不大:


未优化代码:

#include<bits/stdc++.h>
using namespace std;
int n, m, x, y, k[105][105], sum[105][105], ans=0x3f3f3f;
int main() {
	cin >> n >> m;
	for(int i=1; i<=m; i++) {
		cin >> x >> y;
		k[x][y]++;
	}
	for(int len1=1, len2; len1<=m; len1++) { //枚举长宽
		if(m%len1) continue;
		len2=m/len1;
        //枚举起始点
		for(int x1=1; x1+len1-1<=n; x1++) {
			for(int y1=1; y1+len2-1<=n; y1++) {
				int t=0;
                //统计权值为0的点的个数
				for(int x=x1; x<=x1+len1-1; x++) {
					for(int y=y1; y<=y1+len2-1; y++) {
						if(!k[x][y]) t++;
					}
				}
				ans=min(ans, t);
			}
		}
	}
	cout << ans;
}

优化代码:

#include<bits/stdc++.h>
using namespace std;
int n, m, x, y, k[105][105], sum[105][105], ans=0x3f3f3f;
int main() {
	cin >> n >> m;
	for(int i=1; i<=m; i++) {
		cin >> x >> y;
		k[x][y]++;
	}
    //求前缀和
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=n; j++) {
			sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+(!k[i][j]);
		}
	}
	for(int len1=1, len2; len1<=m; len1++) { //枚举长宽
		if(m%len1) continue;
		len2=m/len1;
        //枚举起始点
		for(int x1=1, x2; (x2=x1+len1-1)<=n; x1++) {
			for(int y1=1, y2; (y2=y1+len2-1)<=n; y1++) {
				ans=min(ans, sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]); //更新答案
			}
		}
	}
	cout << ans;
}
posted @ 2024-09-04 09:51  Anins  阅读(14)  评论(0)    收藏  举报  来源