NC202492 仓库选址

题目

题目描述

牛能在某小城有了固定的需求,为了节省送货的费用,他决定在小城里建一个仓库,但是他不知道选在哪里,可以使得花费最小。

给出一个 m×n 的矩阵,代表下一年小城里各个位置对货物的需求次数。我们定义花费为货车载货运输的距离,货车只能沿着水平或竖直方向行驶。

输入描述

首先在一行中输入T,T10,代表测试数据的组数。
每组输入在第一行给出两个正整数 n,m,1n,m100 ,分别代表矩阵的宽和高。
接下来 m 行,每行 n 个不超过 1000 的数字,代表矩阵里的元素。

输出描述

每组输入在一行中输出答案。

示例1

输入

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

输出

2
55
162

备注

送货时只能单次运输,若该位置需要 3 次,货车必须跑 3 次。
即使该位置需要被送货,我们仍然可以选择该位置作为仓库。

题解

知识点:前缀和,枚举。

因为送货按曼哈顿距离(垂直水平的距离)计算费用,故考虑可以将行 x 和列 y 坐标分开确定。

设费用 Px 代表以 x 为行的选址在x方向上消耗的费用,a[i][j] 为某仓库需求次数,s[i][j][1,1]×[i,j]区域需求总数。

考虑递推式 Px+1Px=i=1xj=1na[i][j]i=x+1mj=1na[i][j]=s[x][n](s[m][n]s[x][n])=2s[x][n]s[m][n]

可以看出xx+1 后的费用增量取决于 s[x][n] 与 总量 s[m][n] 的关系。为了使 Px 最小化,尝试从 x=1 开始找到第一个使 Px+1Px 为正 x 。即 2s[x][n]s[m][n] 或者 s[x][n]>s[m][n]2,所以只要找到刚好过半的某个 x 即可(注意后者是整除不能等于)。

同理找到 y 后,以 (x,y) 为选址对全体仓库计算费用即可。

时间复杂度 O(mn)

空间复杂度 O(mn)

代码

#include <bits/stdc++.h>
using namespace std;
int a[107][107],s[107][107];
int main()
{
std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T;
cin>>T;
while(T--)///多组数据要么初始化再加等于,要么输入覆盖再加等于,否则要用等于赋值
{
int n,m;
cin>>n>>m;
for(int i = 1; i<=m; i++)
{
for(int j = 1; j<=n; j++)
{
cin>>a[i][j];
s[i][j] = a[i][j] + s[i][j-1] + s[i-1][j] - s[i-1][j-1];
}
}
int x,y;
for(int i = 1; i<=m; i++)
{
if(s[i][n]>s[m][n]/2)
{
x = i;
break;
}
}
for(int j = 1; j<=n; j++)
{
if(s[m][j]>s[m][n]/2)
{
y = j;
break;
}
}
int ans = 0;
for(int i = 1; i<=m; i++)
{
for(int j = 1; j<=n; j++)
{
ans+=a[i][j]*(abs(i-x)+abs(j-y));
}
}
cout<<ans<<'\n';
}
return 0;
}
posted @   空白菌  阅读(67)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示