.雅虎:
1.对于一个整数矩阵,存 在一种运算,对矩阵中任意元素 加一时,需要其相邻(上下左右)某一个元素也加一,
现给出一正数矩阵,判断 其是 否能够 由一个全零矩阵经过上述运算得到。
2.一个整数 数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
比如{3,2,4, 3,6 } 可以分成{3,2,4,3,6} m=1;
{3,6}{2,4,3} m=2
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
----------------------------------------------------------------------
1:这题我我们自己试着模拟一遍,发现有点类似,扫雷,但是还是有差别的。
我想到了两个制约条件:
(1)某个非零元的值一定小于等于它上下左右的和
(2)整个矩阵的和必须是偶数(因为加1就跟着加另一个1,肯定是偶数)
似乎这两个条件就可以了,难道是必要条件???
我想不到从数学上证明,希望有人能给个清晰的答案。
2:这题我们应该逐步分解,
首先是平均分问题,我们可以分成几份呢?当然最多就是每个元素单独出来,所以最多n份;
其次,是不是1--n这么多都可以呢?不是的,必须总和能够整除份数才行
如果现在需要分成m份,而且能够被数组总和整除,那么就可以计算了,
接下来就是一个数组里找出某几个元素和为total/m 的序列了,
这里类似背包算法,需要用到递归
我这里就引用下面这篇博客代码了,写得比我整齐多了。。。
http://blog.csdn.net/peng_weida/article/details/7741888
#include <cstdio>
#include <cstdlib>
#define NUM 8
int maxShares(int a[], int n);
//aux[i]的值表示数组a中第i个元素分在哪个组,值为0表示未分配
//当前处理的组的现有和 + goal的值 = groupsum
int testShares(int a[], int n, int m, int sum, int groupsum, int aux[], int goal, int groupId);
int main()
{
//int a[] = {2, 6, 4, 1, 3, 9, 7, 5, 8, 10};
//int a[]={2,2,3,5,6,6};
int a[]={1,1,2,2,3,4,5,6};
//打印数组值
printf("数组的值:");
for (int i = 0; i < NUM; i++)
printf(" %d ", a[i]);
printf("\n可以分配的最大组数为:%d\n", maxShares(a, NUM));
return 0;
}
int testShares(int a[], int n, int m, int sum, int groupsum, int aux[], int goal, int groupId)
{
if (goal < 0)
return 0;
if (goal == 0)
{
groupId++;
goal = groupsum;
if (groupId == m+1)
return 1;
}
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;
aux[i] = 0; //a[i]分配失败,将其置为未分配状态
}
return 0;
}
int maxShares(int a[], int n)
{
int sum = 0;
int *aux = (int *)malloc(sizeof(int) * n);
for (int i = 0; i < n; i++)
sum += a[i];
for (int m = n; m >= 2; m--)
{
if (sum%m != 0)
continue;
for (int i = 0; i < n; i++)
aux[i] = 0;
if (testShares(a, n, m, sum, sum/m, aux, sum/m, 1))
{
//打印分组情况
printf("\n分组情况:");
for (int i = 0; i < NUM; i++)
printf(" %d ", aux[i]);
free(aux);
aux = NULL;
return m;
}
}
free(aux);
aux = NULL;
return 1;
}
我的思路和上面差不多,不过上面这个方法借助辅助数组aux[]来表示被访问和分配组别这两个信息 这个技巧不错
而我却是用一个数组来记录当前累加的数字,而是否分配过则通过更改原数组值为0来实现
我的思路比较乱。。
#include <iostream>
using namespace std;
void Print(int *ans, int index);
void H(int k, int sum, int n, int *arr, int dst, int *ans, int index);
bool H2(int k, int sum, int n, int *arr, int dst, int *ans, int index, int* m);
int main() {
int ans[8];
int index=0;
int dst;//每组需要达到的和
int i =0;
int n = 8;//数组元素个数
int m = n;
int total = 24;//这里是数组的总和
for(m=n;m>0;m--){
int test[] = {1,1,2,2,3,4,5,6};
int groupN = m;
if(total%m == 0)
dst = total/m;
else continue;
if(test[n-1]>dst)
continue;
cout<<"分成"<<m<<"组,"<<"每组和为"<<dst<<endl;
for(i=n-1;i>=0;i--){
ans[0] = test[i];
index = 1;
if(ans[0] == dst){
Print(ans, index);groupN--;
continue;
}
if(ans[0] > dst)
continue;
H2(0, ans[0], i, test, dst, ans, index, &groupN);
}
if(groupN != 0)
cout<<"失败"<<endl;
else
cout<<"成功"<<endl;
cout<<"***************"<<endl;
}
return 0;
}
/*
* k表示当前访问到第几个元素
* sum表示当前已累加的和
* arr表示原数组
* dst我们需要达到的和
* ans记录答案
* m 用来表示是否分组成功,每成功一组就减一,直至为0则成功
*/
bool H2(int k, int sum, int n, int *arr, int dst, int *ans, int index, int* m){
int i = k;
for(;i<n;i++){
if(arr[i] == 0)
continue;
int temp = sum + arr[i];
if(temp<dst){
ans[index++] = arr[i];
arr[i] = 0;
if(!H2(i+1, temp, n, arr, dst, ans, index,m))
return false;
index--;
arr[i] = ans[index];
}
else if(temp == dst){
ans[index++] = arr[i];
arr[i] = 0;
Print(ans, index);
(*m)--;
index--;
return false;
}
else{
return true;
}
}
return true;
}
void Print(int *ans, int index){
int i = 0;
for(i=0;i<index;i++)
cout<<ans[i]<<" ";
cout<<endl;
}
分成4组,每组和为6
6
5 1
4 2
3 1 2
成功
***************
分成3组,每组和为8
6 1 1
5 3
4 2 2
成功
***************
分成2组,每组和为12
6 1 1 2 2
5 3 4
成功
***************
分成1组,每组和为24
6 1 1 2 2 3 4 5
成功
***************