隔壁

来源:互联网 发布:mac珊瑚色口红是几号 编辑:程序博客网 时间:2024/04/28 23:24

题目描述

隔壁学校地形图可以通过一个高度矩阵表示,矩阵中每一个位置都有一个数0<=hij<=1000表示这个坐标的海拔,我们姑且将其称为海拔图,容易发现,我们可以通过这个矩阵轻松算出隔壁学校的主视图,左视图。
相反的,我们却不能通过主视图和左视图唯一确定海拔图,现在问题来了,已知主视图左视图,我们需要知道铲平隔壁学校的代价上限和下限(即可能的体积最大值与最小值)

结论题

我们用a[i]表示左视图第i个位置高度,b[i]表示主视图第i个位置高度。
那么就是限定了第i行最大值为a[i],第i列最大值为b[i]。
可以得到每个位置高度取值范围[0,c[i,j]],其中c[i,j]=min(a[i],b[j])
最大值一定是c值的和,此时合法且达到理论最大。
最小值呢?假设每行每列都保留一个c=a或c=b,那么目前答案是a值与b值和,其余位置当然都取高度0啦。
有些位置取了行和列都满足,因此这个答案还可以更优,这些位置满足a[i]=b[j]。
对于一个k,我们把所有a[i]=k和b[j]=k的行和列都提出来,假如提出了l行r列,理论上我们只能让答案最多缩小min(l,r)*k,而我们的确可以达到下界,达到理论最小,这就是最小值的求法,详见代码。

#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=1000+10;int a[maxn],b[maxn],c[maxn][maxn];bool bz[maxn];int i,j,k,l,t,n,m,mi,mx;int main(){    freopen("neighbor.in","r",stdin);freopen("neighbor.out","w",stdout);    scanf("%d%d",&n,&m);    fo(i,1,n) scanf("%d",&a[i]);    fo(i,1,m) scanf("%d",&b[i]);    fo(i,1,n)        fo(j,1,m)            c[i][j]=min(a[i],b[j]);    fo(i,1,n) mi+=a[i];    fo(i,1,m) mi+=b[i];    fo(i,1,n){        fo(j,1,m)            if (!bz[j]&&c[i][j]==a[i]&&c[i][j]==b[j]){                bz[j]=1;                mi-=a[i];                break;            }    }    printf("%d ",mi);    fo(i,1,n)        fo(j,1,m)            mx+=c[i][j];    printf("%d\n",mx);}
0 0
原创粉丝点击