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;
}