2017微众银行校招实习

小B特别喜欢玩一款模拟城市建设的游戏,她觉得看着城市从自己的手中诞生超有成就感。游戏地图是一个由n*m个单元构成的矩形区域,每个单元的属性为其平均高度。小B的任务是在其中建设若干城市,每个城市为地图中a*b个单元大小的矩形区域。
为开展城市建设,需要先平整土地。小B的做法是从选定的区域中选择最低的单元,将其他单元平整为与该单元相同的高度。把高度为h2的单元平整到高度h1时,需要挖掘h2-h1单位的土石。为减少土石挖掘量,需要选择最佳的建设地点,使得挖掘的土石量最小。
小B按照如下方式开展城市建设工作,从所有可能的最佳建设地点中选择位于最上方的那个,若存在多个,则选择最左侧的位置,并在该位置开始城市建设工作。重复该过程以建成其他城市。若有单元已经被占用,则不能在其上开展建设工作。你能帮助小B找到合适的城市建设位置吗?
输入
测试数据有多组,每组测试数据的第一行为四个整数n, m, a, b(1=< a =< n <=1000, 1=< b =< m <=1000),表示地图的大小和城市的大小。随后的n行中每行有m个非负整数,表示区域中各个单元的平均高度,每个整数大小不超过10^9。
输出
对每组测试数据,先在第一行中输出一个数k,表示可以建设的城市数,在紧随其后的k行中,每行输出3个空格分隔的整数,分别表示该城市所在位置的左上角行号、列号以及需要挖掘的土石量。


样例输入
2 2 1 2
1 2
3 5
4 4 2 2
1 5 3 4
2 7 6 1
1 1 2 2
2 2 1 2
样例输出
2
1 1 1
2 1 2
3
3 1 2
3 3 3

1 2 9

#include  <iostream> 
#include  <vector>
using namespace std;
int main()
{
	int n, m, a, b;
	while (cin >> n >> m >> a >> b) {
		int* map = new int[n*m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++)
				cin >> map[i*m + j];
		}

		int* cost = new int[n*m];
		memset(cost, -1, n*m*sizeof(int));
		bool* visited = new bool[n*m];
		memset(visited, false, n*m*sizeof(bool));

		// calculate all cost
		int min = 0, sum = 0, count = 0;
		for (int i = 0; i < n - a + 1; i++) {
			for (int j = 0; j < m - b + 1; j++) {
				min = map[i*n + j];
				sum = 0;
				for (int a1 = 0; a1 < a; a1++) {
					for (int b1 = 0; b1 < b; b1++) {
						sum += map[(i + a1)*n + j + b1];
						if (map[(i + a1)*n + j + b1] < min)
							min = map[(i + a1)*n + j + b1];
					}
				}
				sum -= a*b * min;
				cost[i*n + j] = sum;
				count++;
			}
		}

		// print
		int min_cost = 1e10, min_i = -1, min_j = -1;
		vector<int> aa, bb, cc;
		while (count-- > 0) {
			min_cost = 1e10, min_i = -1, min_j = -1;
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < m; j++) {
					bool v = false;
					for (int a1 = 0; a1 < a; a1++) {
						for (int b1 = 0; b1 < b; b1++) {
							if (visited[(i + a1)*n + j + b1] == true)
								v = true;
						}
					}
					if (v == false && cost[i*n + j] >= 0 && cost[i*n + j] < min_cost) {
						min_cost = cost[i*n + j];
						min_i = i;
						min_j = j;
					}
				}
			}
			if (min_i != -1) {
				for (int a1 = 0; a1 < a; a1++) {
					for (int b1 = 0; b1 < b; b1++) {
						if (visited[(min_i + a1)*n + min_j + b1] == false)
							visited[(min_i + a1)*n + min_j + b1] = true;
					}
				}

				aa.push_back(min_i + 1);
				bb.push_back(min_j + 1);
				cc.push_back(min_cost);
			}
		}
		cout << aa.size() << endl;
		for (int i = 0; i < aa.size(); i++) {
			cout << aa[i] << " " << bb[i] << " " << cc[i] << endl;
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值