对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一

1. 对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一,

现给出一正数矩阵,判断其是否能够由一个全零矩阵经过上述运算得到。


2. 一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
  比如{3,2,4,3,6} 可以分成{3,2,4,3,6} m=1; 
  {3,6}{2,4,3} m=2
  {3,3}{2,4}{6} m=3 所以m的最大值为3

一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
  比如{3,2,4,3,6} 可以分成{3,2,4,3,6} m=1;
  {3,6}{2,4,3} m=2
  {3,3}{2,4}{6} m=3 所以m的最大值为3

算法 原理的思想是将大问题转换成小问题。
就{3,2,4,3,6}的操作步骤:
      第一步:想将数组递减排序得{6,4,3,3,2},求出数组中所有数的和m=18,第一个最大的数b=6, m/b=3余数为0,
当除数为1,余数为0时终止。当余数不为0时,转到第三步。当余数为0时将数组划分为{6},{4,3,3,2}两个。把{4,3,3,2}看成一个新的数组。
      第二步:先用{4,3,3,2}中的最大数与b=6比较,即4<b,所以再将4与最右边的数即2相加与b比较,
结果相等,则将这两个数从该数组中除去生成新的数组,转到第一步,现在的结果是{6},{4,2},{3,3},把{3,3}看成一个新的数组继续重复第二步。
      第三步,将数组中最大的数与最小的数取出构成一个新数组Z,剩余的构成一个数组,然后,
判断m/Z中数字之和看是否余数为0,若为0,把b替换为Z中数字之和转第二步,若不为0,
继续从剩余的数字中取出最小值加入到Z中,再判断m/Z中数字之和看是否余数为0,直到为0,转第二步为止。
最后得到的结果是{6},{4,2},{3,3} 这时可以计算出m为3,也可以在程序中作记载。
在第二步工程过,若出现两个数相加大于上一次的b,则将程序转到第三步。


 

// p44_YahooReviewerQ.cpp : Defines the entry point for the console application.
//
//--------------------------------------------------------------------------------------
/*
	1.对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)
	某一个元素也加一,现给出一正数矩阵,判断其是否能够由一个全零矩阵经过上述运算得到。
*/
/*
	2.一个整数数组,长度为n,将其分为m 份,使各份的和相等,求m 的最大值
	比如{3,2,4,3,6} 可以分成{3,2,4,3,6} m=1;
	{3,6}{2,4,3} m=2
	{3,3}{2,4}{6} m=3 所以m 的最大值为3
*/
//--------------------------------------------------------------------------------------
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <stack>
#include <math.h>

using namespace std;

#define	INIT_SIZE	100

#define Q_MODE_		1	// 若为 1:表示第一题;若为 2:表示为第二题;

int nMaxtric[INIT_SIZE][INIT_SIZE];
int nXLen = 0;
int nYLen = 0;

int nArray[INIT_SIZE];
int nACurLen = 0;
// 判断是否可以由零矩阵转换而得
//-------------------------------------------------
// 注:算法 不知,只知道每次增加 5,即矩阵和为 5 的
//	   倍数。	
//-------------------------------------------------
// 判读改点是 模板否?...
bool testPosIsTemplate(int nMaxtric[INIT_SIZE][INIT_SIZE],int nXLen,int nYLen,int nXPos,int nYPos)
{
	bool bIs = false;
	int nUp_x = 0,nDown_x = 0,nLeft_x = 0,nRight_x = 0;
	int nUp_y = 0,nDown_y = 0,nLeft_y = 0,nRight_y = 0;

	nUp_x = nXPos-1;	nUp_y = nYPos;
	nDown_x = nXPos+1;nDown_y = nYPos;
	nLeft_x = nXPos;nLeft_y = nYPos-1;
	nRight_x = nXPos;nRight_y = nYPos+1;

	if(nUp_x <= 0)nUp_x = 0;
	if(nUp_x >= nXLen)nUp_x = nXLen - 1;
	if(nDown_x <= 0)nDown_x = 0;
	if(nDown_x >= nXLen)nDown_x = nXLen - 1;
	if(nLeft_x <= 0)nLeft_x = 0;
	if(nLeft_x >= nXLen)nLeft_x = nXLen - 1;
	if(nRight_x <= 0)nRight_x = 0;
	if(nRight_x >= nXLen)nRight_x = nXLen - 1;

	if(nUp_y <= 0)nUp_y = 0;
	if(nUp_y >= nYLen)nUp_y = nYLen - 1;
	if(nDown_y <= 0)nDown_y = 0;
	if(nDown_y >= nYLen)nDown_y = nYLen - 1;
	if(nLeft_y <= 0)nLeft_y = 0;
	if(nLeft_y >= nYLen)nLeft_y = nYLen - 1;
	if(nRight_y <= 0)nRight_y = 0;
	if(nRight_y >= nYLen)nRight_y = nYLen - 1;

	if(nMaxtric[nXPos][nYPos] && nMaxtric[nUp_x][nUp_y] && nMaxtric[nDown_x][nDown_y] &&
		nMaxtric[nLeft_x][nLeft_y] && nMaxtric[nRight_x][nRight_y])
		bIs = true;

	return bIs;
}
// 判读是否为零矩阵
bool isZeroMaxtric(int nMaxtric[INIT_SIZE][INIT_SIZE],int nXLen,int nYLen)
{
	bool bIsZ = true;

	for(int i = 0;i < nXLen;i ++)
		for(int j = 0;j < nYLen;j ++)
		{
			if(nMaxtric[i][j])
			{
				bIsZ = false;
				goto END;
			}
		}
END:
	return bIsZ;

}
// 减去模板矩阵
bool DecTeplateMaxtric(int nMaxtric[INIT_SIZE][INIT_SIZE],int nXLen,int nYLen,int nXPos,int nYPos)
{
	int nUp_x = 0,nDown_x = 0,nLeft_x = 0,nRight_x = 0;
	int nUp_y = 0,nDown_y = 0,nLeft_y = 0,nRight_y = 0;

	nUp_x = nXPos;	nUp_y = nYPos-1;
	nDown_x = nXPos;nDown_y = nYPos+1;
	nLeft_x = nXPos-1;nLeft_y = nYPos;
	nRight_x = nXPos+1;nRight_y = nYPos;
	
	nMaxtric[nXPos][nYPos] -= 1;
	if(nUp_x >= 0 && nUp_x < nXLen && nUp_y >= 0 && nUp_y < nYLen)nMaxtric[nUp_x][nUp_y] -= 1;
	if(nDown_x >= 0 && nDown_x < nXLen && nDown_y >= 0 && nDown_y < nYLen)nMaxtric[nDown_x][nDown_y] -= 1;
	if(nLeft_x >= 0 && nLeft_x < nXLen && nLeft_y >= 0 && nLeft_y < nYLen)nMaxtric[nLeft_x][nLeft_y] -= 1;
	if(nRight_x >= 0 && nRight_x < nXLen && nRight_y >= 0 && nRight_y < nYLen)nMaxtric[nRight_x][nRight_y] -= 1;
	
	return true;
}
// 递归判读
bool MaxtricTrans(int nMaxtric[INIT_SIZE][INIT_SIZE],int nXLen,int nYLen)
{
	if(isZeroMaxtric(nMaxtric,nXLen,nYLen))return true;

	for(int i = 0;i < nXLen;i ++)
		for(int j = 0;j <nYLen;j ++)
		{
			if(testPosIsTemplate(nMaxtric,nXLen,nYLen,i,j))
			{
				DecTeplateMaxtric(nMaxtric,nXLen,nYLen,i,j);
				goto END;
			}
		}

	return isZeroMaxtric(nMaxtric,nXLen,nYLen);
END:
	if(MaxtricTrans(nMaxtric,nXLen,nYLen))return true;
	else return false;
}
bool isMaxtricTrans(int nMaxtric[INIT_SIZE][INIT_SIZE],int nXLen,int nYLen)
{
	if(nMaxtric == NULL	||
		nXLen <=	0	||
		nYLen <=	0)
		return false;

	bool bTrue = false;
	
	bTrue = MaxtricTrans(nMaxtric,nXLen,nYLen);
	
	if(bTrue)cout << "可以" <<endl;
	else	 cout << "不可以" <<endl;

	return true;
}
// 判读数组最大可分的数组份数
bool getMaxAveSumOfArray(int nArray[INIT_SIZE],int nACurLen)
{
	if(nArray == NULL	||
		nACurLen <= 0)
		return false;
	

	return true;
}
//-----------------------------------------------------------------------------
// 答案:
//		此处也是经典案例啊!....
int testShares(int a[], int n, int m, int sum, int groupsum, int aux[], int goal, int& groupId)	// 注,此处必须加引用,不然出错,因为值传递错误
{
  if (goal == 0) 
  {
    groupId++;
    if (groupId == m+1) return 1;
 
	return 0;	// 增加返回,提供程序效率
  }
  for (int i=0; i <n; i++) 
  {
    if (aux[i] != 0) continue;
    aux[i] = groupId;

    if(testShares(a, n, m, sum, groupsum, aux, goal-a[i], groupId))
	{
      return 1;
    }
	else
		aux[i] = 0;
  }
  return 0;
}
int maxShares(int a[], int n)
{
  int sum = 0;
  int i, m;
  for (i=0; i <n; i++) sum += a[i];
  for (m=n; m >=2; m--) 
  {
    if (sum % m != 0) continue;
    int aux[INIT_SIZE]; 
	int groupId = 1;
	for (i=0; i < INIT_SIZE; i++) aux[i] = 0;
    if (testShares(a, n, m, sum, sum/m, aux, sum/m, groupId)) return m;
  }
  return 1;
}

int main(int argc, char* argv[])
{
	memset(nMaxtric,0,sizeof(int)*INIT_SIZE*INIT_SIZE);
	memset(nArray,0,sizeof(int)*INIT_SIZE);

	int nNum = 0;
#if(Q_MODE_  == 1)
	cout<<"请输入nMaxtric 相应的数据<输入符号时结束相应的 行/列 输入>:\n"<<endl;
	int nX = 1,nY = 1;
	while(1)
	{
		cout<<"请输入第"<<nX<<"行数据"<<endl;
		cin>>nNum;
		if (cin.fail())
		{
			break;
		}
		else
		{
			nMaxtric[nX-1][nY-1] = nNum;
			nY++;
		}
		// 继续输入改行的数据
		while(1)
		{
			cin>>nNum;
			if (cin.fail())
			{
				// 更新X轴的最大值
				if(nY > nXLen)nXLen = nY-1;
				//清理缓冲区
				cin.clear();
				cin.ignore(1000,'\n');
				break;
			}
			else
			{
				nMaxtric[nX-1][nY-1] = nNum;
				nY++;
			}
		}

		nX++;
		nY = 1;
	}
	nYLen = nX-1;

	if(!isMaxtricTrans(nMaxtric,nYLen,nXLen))
	{
		cout << "Param Error!..."<<endl;
	}
#else if(Q_MODE_ == 2)
	cout<<"请输入数组相应的数据<输入符号时结束输入>:\n"<<endl;	
	while(nACurLen <= INIT_SIZE)
	{
		cin>>nNum;
		if (cin.fail())
		{
			break;
		}
		else
		{
			nArray[nACurLen ++] = nNum;
		}
	}

	cout << "最大的可分份数为 "<< maxShares(nArray,nACurLen)<< endl;
#endif

	cin.ignore(1000,'\n');  //清理缓冲区
	getch();
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值