名企笔试:网易2017内推笔试编(分田地)2017-03-22 算法爱好者

 
 
名企笔试:网易2017内推笔试编(分田地)2017-03-22 算法爱好者

牛牛和 15 个朋友来玩打土豪分田地的游戏,牛牛决定让你来分田地,
地主的田地可以看成是一个矩形,每个位置有一个价值。
分割田地的方法是横竖各切三刀,分成 16 份,作为领导干部,
牛牛总是会选择其中总价值最小的一份田地, 作为牛牛最好的朋友,
你希望牛牛取得的田地的价值和尽可能大,你知道这个值最大可以是多少吗?

输入描述:
每个输入包含 1 个测试用例。
每个测试用例的第一行包含两个整数 n 和 m(1 <= n, m <= 75),表示田地的大小,
接下来的 n 行,每行包含 m 个 0-9 之间的数字,表示每块位置的价值

输出描述:
输出一行表示牛牛所能取得的最大的价值。

输入例子:
4 4
3332
3233
3332
2323

输出例子:

2

C++源代码:

//	Netease peoblem 2017.03.22
//	2017.03.22 by wyj

/*
名企笔试:网易2017内推笔试编(分田地)2017-03-22 算法爱好者

牛牛和 15 个朋友来玩打土豪分田地的游戏,牛牛决定让你来分田地,
地主的田地可以看成是一个矩形,每个位置有一个价值。
分割田地的方法是横竖各切三刀,分成 16 份,作为领导干部,
牛牛总是会选择其中总价值最小的一份田地, 作为牛牛最好的朋友,
你希望牛牛取得的田地的价值和尽可能大,你知道这个值最大可以是多少吗?

输入描述:
每个输入包含 1 个测试用例。
每个测试用例的第一行包含两个整数 n 和 m(1 <= n, m <= 75),表示田地的大小,
接下来的 n 行,每行包含 m 个 0-9 之间的数字,表示每块位置的价值

输出描述:
输出一行表示牛牛所能取得的最大的价值。

输入例子:
4 4
3332
3233
3332
2323

输出例子:
2
*/

#include
    
    
     
     
#include
     
     
      
      
using namespace std;

int row, vol;	

int main()
{
//	int Find_Min(int A[4][4]);
	int Split_Min(int A[75][75], int Row[5], int Vol[5]);
	int i, j;
	int C[75][75];		
	int Min = 0;
	int Row[5], Vol[5];		//分割线,Row[i]为在第i行前画一条横线,Vol[j]为在第j列前画一条竖线
	int r1, r2, r3, v1, v2, v3;		//记录下来最优情况下的分割方法
	
	cin >> row >> vol;			//输入矩阵的行、列数
	for (i = 0;i < row;i++)			//输入矩阵
		for (j = 0;j < vol;j++)
			cin >> C[i][j];
	
	Row[0] = 0;Row[4] = row;
	Vol[0] = 0;Vol[4] = vol;
	for (Row[1] = 1;Row[1] <= row - 3;Row[1]++)		//所有分割方法
		for (Row[2] = Row[1] + 1;Row[2] <= row - 2;Row[2]++)
			for (Row[3] = Row[2] + 1;Row[3] <= row - 1;Row[3]++)
				for (Vol[1] = 1;Vol[1] <= vol - 3;Vol[1]++)
					for (Vol[2] = Vol[1] + 1;Vol[2] <= vol - 2;Vol[2]++)
						for (Vol[3] = Vol[2] + 1;Vol[3] <= vol - 1;Vol[3]++)
						{
							int t = Split_Min(C, Row, Vol);		//求一种分割方法下的最小值
							if (t > Min)				//求所有最小值中的最大值
							{
								Min = t;
								r1 = Row[1];r2 = Row[2];r3 = Row[3];	//记录分割方法
								v1 = Vol[1];v2 = Vol[2];v3 = Vol[3];
							}
						}
	cout << "Min=" << Min << endl;
	cout << "r:" << r1 << "," << r2 << "," << r3 << endl;
	cout << "v:" << v1 << "," << v2 << "," << v3 << endl;
	return 0;
}

//分割矩阵并求16个子块的最小值
int Split_Min(int A[75][75],int Row[5],int Vol[5])
{
	int i, j, k = 0;
	int t[16] = { 0 };
	int r, v;
	int Min = 100000;
	for (k = 0;k < 16;k++)
	{
		r = k / 4, v = k % 4;
		for (i = Row[r];i < Row[r + 1];i++)
			for (j = Vol[v];j < Vol[v + 1];j++)
				t[k] += A[i][j];
		if (t[k] < Min)
			Min = t[k];	
	}
//	cout << "min:" << Min << endl;
	return Min;
}

/*
测试数据:

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

4 4
3 3 3 2
3 2 3 3
3 3 3 2
2 3 2 3
*/
     
     
    
    
测试数据:
7 8 0 1 2 3 4 5 6 7 1 0 4 2 3 5 1 6 2 1 1 3 5 7 1 0 3 3 2 4 2 3 1 2 4 4 1 4 1 3 1 1 5 5 2 1 2 2 0 0 6 6 3 2 3 1 2 7 4 4 3 3 3 2 3 2 3 3 3 3 3 2 2 3 2 3

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值