仓库选址(前缀和、数学)

在这里插入图片描述
解题思路:
二维前缀和(O(NM))
这个算法可能比较简单易懂,二维前缀和的实现与计算就不再赘述了,可以上网查一下
在暴力方法一中每次枚举一个坐标都要把到所有点的距离重新算一遍,其实没必要。
若仓库在点 (x,y) 处,现在将仓库移动到点 (x+1,y) ,那么对于左上角为(1,1),右下角为(x,m)的矩阵,所有点到达仓库的距离都+1,对于左上角为(x+1,1),右下角为(n,m)的矩阵,所有点到达仓库的距离都-1。若仓库在点 (x,y) 处,现在将仓库移动到点 (x,y+1)同理计算即可。

#include<bits/stdc++.h>
using namespace std;
int s[110][110];
inline int calc(int A,int B,int C,int D)
{
	return s[C][D]-s[A-1][D]-s[C][B-1]+s[A-1][B-1];
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int m,n,now=0,nxt=0,ans=0x3f3f3f3f;
		cin>>m>>n;
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=m;++j)
			{
				int a;
				cin>>a;
				s[i][j]=a+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
				now+=a*(i-1+j-1);
			}
		}
		for(int i=1;i<=n;++i)
		{
			nxt=now;
			for(int j=1;j<=m;++j)
			{
				ans=min(nxt,ans);
				nxt+=calc(1,1,n,j)-calc(1,j+1,n,m);
			}
			now+=calc(1,1,i,m)-calc(i+1,1,n,m);
		}
		cout<<ans<<endl;
	}
	return 0;
}
发布了165 篇原创文章 · 获赞 11 · 访问量 4885

猜你喜欢

转载自blog.csdn.net/weixin_43784305/article/details/105098297