题目描述

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

输入

第一行两个数 n , m (1 <=n ,m<=1000,  0<= hi ,j <= 1000), 分别表示海拔图的长和宽。

第二行 n 个数,描述了主视图每一个位置的高度。

第三行 m 个数,描述了左视图每一个位置的高度

输出

一行两个数,分别表示代价最小值与最大值。

样例输入

2 2
1 1
1 1

样例输出

2 4

思路:  从正面和左面都应当看到这些建筑物,要求最小高度和,从正面和左面看到高度相同的建筑物 为同一建筑物,高度不同的肯定不能为同一座建筑物,因为建筑物不能悬空。

求最大建筑物和我用了暴力的方法,就是先将地图每一列所有点的高度都等于主视图该列的高度,然后再遍历每一行,如果这一行的那座建筑物高过左视图这一行的高度就削去这座建筑物多余的高度。

#include <iostream>
#include <cstring>
 
using namespace std;
 
const int N = 1010;
int a[N], b[N];
// a[] 主视图 , b[]左视图 
int c[N][N]; 
int vis[N];
// vis[i] = 1 则主视图中有 高度为 i 的建筑物
// vis[i] = 0 则主视图中无 高度为 i 的建筑物
 
int main()
{
    int n, m;
    cin >> n >> m;
    long long ans = 0;
    memset(vis, 0, sizeof(vis));
 
    for(int i=1; i<=n; i++) {
        cin >> a[i];
        ans += a[i];
        vis[a[i]] ++;
    }
     
 /*   for(int i=0; i<=10; i++)
       cout << vis[i] << endl;
       cout << endl;*/
        
    for(int i=1; i<=m; i++) {
        cin >> b[i];
        ans += b[i];
    }
     
    for(int i=1; i<=m; i++) {
         
    //  cout << b[i] << endl;
        if(vis[b[i]] > 0){
           ans -= b[i];
         //  cout << ans << endl;
           vis[b[i]] --;
         }
    }
 
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            c[j][i] = a[i];
            //  就是先将地图按每一列所有点的高度都等于主视图该列的高度
        }
    }
 
    long long res = 0;
    for(int i=1; i<=m; i++) {
        for(int j=1; j<=n; j++) {
            if(c[i][j] > b[i]) {
            	//  遍历每一行,如果这一行的那座建筑物高过左视图这一行的高度就削去这座建筑物多余的高度
            	// 这里没有削去,直接按削去后的高度计算,算是降低时间复杂度吧 
                res += b[i];
            }
            else
                res += c[i][j];
        }
    }
    cout << ans << " " << res << endl;
    return 0;
}