45.雅虎(运算、矩阵):
1.对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)
某一个元素也加一,现给出一正数矩阵,判断其是否能够由一个全零矩阵经过上述运算得到。

这道题,是我目前为止做过的最最最最最麻烦、最繁琐的题目了。

思路:

把输入的矩阵一步步还原成 0 矩阵

一个数字,只可能伴随着它上下左右四个方向的数字变化。

①如果数字比它周围四个数的和要大,那么一定不满足条件。

②如果数字小于等于四周的数字和,且其四周仅有一个数字不为0: 不为0的那个周围数字的大小 -= 当前数字大小,将当前数字置零。  因为当前数字仅可能是那个不为0的数字引起的。

③如果数字等于四周的数字和,且其四周仅有多个个数字不为0:当前与四周的数字均置0。

④如果数字小于四周的数字和,且其四周仅有多个个数字不为0:无法判断,循环继续还原。

思路不难,但是对于矩阵的四个角、四条边和中间必须分开处理,让整个代码显得又臭又长!但实际上,跟一份代码被copy了9遍差不多。我还没有什么化简的方法。如果有人知道,希望可以告诉我。

/*
45.雅虎(运算、矩阵):
1.对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)
某一个元素也加一,现给出一正数矩阵,判断其是否能够由一个全零矩阵经过上述运算得到。
*/
#include <stdio.h>bool canBeCreatedbyZero(int ** M, int row, int col)
{bool flag = false;do {flag =false;for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++){//打印每一次处理后的矩阵情况printf("\n");for (int r = 0; r < row; r++){for(int c = 0; c < col; c++){printf("%d", *((int *)M + r * col + c));}printf("\n");}if ((i == 0) &&(j != 0 && j != col - 1)) //最上边
                {int * r = (int *)M + i * col;int * r1 = (int *)M + (i + 1) * col; if((r[j - 1] != 0 || r[j] != 0 || r[j + 1] != 0 || r1[j] != 0)) //只在有非零元素的时候才做下面处理
                    {    flag = true;int has[3][2];int hasnum = 0; //该中心点上下左右有几个不为0的数字int sum = 0; //该中心点四周的数字相加的值if (r[j - 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j - 1;hasnum++;}if (r[j + 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j + 1;hasnum++;}if (r1[j] != 0){has[hasnum][0] = i + 1;has[hasnum][1] = j;hasnum++;}sum = r[j - 1] + r[j + 1] + r1[j];if (r[j] > sum) //数字大于周围的和 返回false
                        {return false;}else if(hasnum == 1) //旁边只有一个不为0的 中心数字与旁边数字同步减少
                        {int t = r[j];r[j] = 0;*((int *)M + has[0][0] * col + has[0][1]) -= t;}else if(r[j] == sum) //中心数字与旁边不为0的数字和相等
                        {for(int ii = 0; ii < hasnum; ii++){*((int *)M + has[ii][0] * col + has[ii][1]) = 0;}r[j] = 0;}}}else if((i == row - 1) &&(j != 0 && j != col - 1)) //最下边
                {int * r_1 = (int *)M + (i - 1) * col;int * r = (int *)M + i * col;if((r_1[j] != 0 || r[j - 1] != 0 || r[j] != 0 || r[j + 1] != 0)) //只在有非零元素的时候才做下面处理
                    {    flag = true;int has[4][2];int hasnum = 0; //该中心点上下左右有几个不为0的数字int sum = 0; //该中心点四周的数字相加的值if (r_1[j] != 0){has[hasnum][0] = i - 1;has[hasnum][1] = j;hasnum++;}if (r[j - 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j - 1;hasnum++;}if (r[j + 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j + 1;hasnum++;}sum = r_1[j] + r[j - 1] + r[j + 1];if (r[j] > sum) //数字大于周围的和 返回false
                        {return false;}else if(hasnum == 1) //旁边只有一个不为0的 中心数字与旁边数字同步减少
                        {int t = r[j];r[j] = 0;*((int *)M + has[0][0] * col + has[0][1]) -= t;}else if(r[j] == sum) //中心数字与旁边不为0的数字和相等
                        {for(int ii = 0; ii < hasnum; ii++){*((int *)M + has[ii][0] * col + has[ii][1]) = 0;}r[j] = 0;}}}else if ((j == 0) &&(i != 0 && i != row - 1)) //最左边
                {int * r_1 = (int *)M + (i - 1) * col;int * r = (int *)M + i * col;int * r1 = (int *)M + (i + 1) * col; if((r_1[j] != 0 || r[j] != 0 || r[j + 1] != 0 || r1[j] != 0)) //只在有非零元素的时候才做下面处理
                    {    flag = true;int has[4][2];int hasnum = 0; //该中心点上下左右有几个不为0的数字int sum = 0; //该中心点四周的数字相加的值if (r_1[j] != 0){has[hasnum][0] = i - 1;has[hasnum][1] = j;hasnum++;}if (r[j + 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j + 1;hasnum++;}if (r1[j] != 0){has[hasnum][0] = i + 1;has[hasnum][1] = j;hasnum++;}sum = r_1[j] + r[j + 1] + r1[j];if (r[j] > sum) //数字大于周围的和 返回false
                        {return false;}else if(hasnum == 1) //旁边只有一个不为0的 中心数字与旁边数字同步减少
                        {int t = r[j];r[j] = 0;*((int *)M + has[0][0] * col + has[0][1]) -= t;}else if(r[j] == sum) //中心数字与旁边不为0的数字和相等
                        {for(int ii = 0; ii < hasnum; ii++){*((int *)M + has[ii][0] * col + has[ii][1]) = 0;}r[j] = 0;}}}else if ((j == col - 1) &&(i != 0 && i != row - 1)){int * r_1 = (int *)M + (i - 1) * col;int * r = (int *)M + i * col;int * r1 = (int *)M + (i + 1) * col; if((r_1[j] != 0 || r[j - 1] != 0 || r[j] != 0 || r1[j] != 0)) //只在有非零元素的时候才做下面处理
                    {    flag = true;int has[4][2];int hasnum = 0; //该中心点上下左右有几个不为0的数字int sum = 0; //该中心点四周的数字相加的值if (r_1[j] != 0){has[hasnum][0] = i - 1;has[hasnum][1] = j;hasnum++;}if (r[j - 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j - 1;hasnum++;}if (r1[j] != 0){has[hasnum][0] = i + 1;has[hasnum][1] = j;hasnum++;}sum = r_1[j] + r[j - 1] + r1[j];if (r[j] > sum) //数字大于周围的和 返回false
                        {return false;}else if(hasnum == 1) //旁边只有一个不为0的 中心数字与旁边数字同步减少
                        {int t = r[j];r[j] = 0;*((int *)M + has[0][0] * col + has[0][1]) -= t;}else if(r[j] == sum) //中心数字与旁边不为0的数字和相等
                        {for(int ii = 0; ii < hasnum; ii++){*((int *)M + has[ii][0] * col + has[ii][1]) = 0;}r[j] = 0;}}}else if ( i == 0 && j == 0) //左上角
                {int * r = (int *)M + i * col;int * r1 = (int *)M + (i + 1) * col; if(( r[j] != 0 || r[j + 1] != 0 || r1[j] != 0)) //只在有非零元素的时候才做下面处理
                    {    flag = true;int has[4][2];int hasnum = 0; //该中心点上下左右有几个不为0的数字int sum = 0; //该中心点四周的数字相加的值if (r[j + 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j + 1;hasnum++;}if (r1[j] != 0){has[hasnum][0] = i + 1;has[hasnum][1] = j;hasnum++;}sum = r[j + 1] + r1[j];if (r[j] > sum) //数字大于周围的和 返回false
                        {return false;}else if(hasnum == 1) //旁边只有一个不为0的 中心数字与旁边数字同步减少
                        {int t = r[j];r[j] = 0;*((int *)M + has[0][0] * col + has[0][1]) -= t;}else if(r[j] == sum) //中心数字与旁边不为0的数字和相等
                        {for(int ii = 0; ii < hasnum; ii++){*((int *)M + has[ii][0] * col + has[ii][1]) = 0;}r[j] = 0;}}}else if (i == row - 1 && j == 0) //左下角
                {int * r_1 = (int *)M + (i - 1) * col;int * r = (int *)M + i * col;if((r_1[j] != 0|| r[j] != 0 || r[j + 1] != 0)) //只在有非零元素的时候才做下面处理
                    {    flag = true;int has[4][2];int hasnum = 0; //该中心点上下左右有几个不为0的数字int sum = 0; //该中心点四周的数字相加的值if (r_1[j] != 0){has[hasnum][0] = i - 1;has[hasnum][1] = j;hasnum++;}if (r[j + 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j + 1;hasnum++;}sum = r_1[j] + r[j + 1];if (r[j] > sum) //数字大于周围的和 返回false
                        {return false;}else if(hasnum == 1) //旁边只有一个不为0的 中心数字与旁边数字同步减少
                        {int t = r[j];r[j] = 0;*((int *)M + has[0][0] * col + has[0][1]) -= t;}else if(r[j] == sum) //中心数字与旁边不为0的数字和相等
                        {for(int ii = 0; ii < hasnum; ii++){*((int *)M + has[ii][0] * col + has[ii][1]) = 0;}r[j] = 0;}}}else if (i == 0 && j == col - 1) //右上角
                {int * r = (int *)M + i * col;int * r1 = (int *)M + (i + 1) * col; if((r[j - 1] != 0 || r[j] != 0 || r1[j] != 0)) //只在有非零元素的时候才做下面处理
                    {    flag = true;int has[4][2];int hasnum = 0; //该中心点上下左右有几个不为0的数字int sum = 0; //该中心点四周的数字相加的值if (r[j - 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j - 1;hasnum++;}if (r1[j] != 0){has[hasnum][0] = i + 1;has[hasnum][1] = j;hasnum++;}sum = r[j - 1] + r1[j];if (r[j] > sum) //数字大于周围的和 返回false
                        {return false;}else if(hasnum == 1) //旁边只有一个不为0的 中心数字与旁边数字同步减少
                        {int t = r[j];r[j] = 0;*((int *)M + has[0][0] * col + has[0][1]) -= t;}else if(r[j] == sum) //中心数字与旁边不为0的数字和相等
                        {for(int ii = 0; ii < hasnum; ii++){*((int *)M + has[ii][0] * col + has[ii][1]) = 0;}r[j] = 0;}}}else if (i == row - 1 && j == col - 1) //右下角
                {int * r_1 = (int *)M + (i - 1) * col;int * r = (int *)M + i * col;if(r_1[j] != 0 || r[j - 1] != 0 || r[j] != 0) //只在有非零元素的时候才做下面处理
                    {    flag = true;int has[4][2];int hasnum = 0; //该中心点上下左右有几个不为0的数字int sum = 0; //该中心点四周的数字相加的值if (r_1[j] != 0){has[hasnum][0] = i - 1;has[hasnum][1] = j;hasnum++;}if (r[j - 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j - 1;hasnum++;}sum = r_1[j] + r[j - 1];if (r[j] > sum) //数字大于周围的和 返回false
                        {return false;}else if(hasnum == 1) //旁边只有一个不为0的 中心数字与旁边数字同步减少
                        {int t = r[j];r[j] = 0;*((int *)M + has[0][0] * col + has[0][1]) -= t;}else if(r[j] == sum) //中心数字与旁边不为0的数字和相等
                        {for(int ii = 0; ii < hasnum; ii++){*((int *)M + has[ii][0] * col + has[ii][1]) = 0;}r[j] = 0;}}}else if(i != 0 && i != row - 1 && j != 0 && j != col - 1) //非边界情况
                {int * r_1 = (int *)M + (i - 1) * col;int * r = (int *)M + i * col;int * r1 = (int *)M + (i + 1) * col; if((r_1[j] != 0 || r[j - 1] != 0 || r[j] != 0 || r[j + 1] != 0 || r1[j] != 0)) //只在有非零元素的时候才做下面处理
                    {    flag = true;int has[4][2];int hasnum = 0; //该中心点上下左右有几个不为0的数字int sum = 0; //该中心点四周的数字相加的值if (r_1[j] != 0){has[hasnum][0] = i - 1;has[hasnum][1] = j;hasnum++;}if (r[j - 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j - 1;hasnum++;}if (r[j + 1] != 0){has[hasnum][0] = i;has[hasnum][1] = j + 1;hasnum++;}if (r1[j] != 0){has[hasnum][0] = i + 1;has[hasnum][1] = j;hasnum++;}sum = r_1[j] + r[j - 1] + r[j + 1] + r1[j];if (r[j] > sum) //数字大于周围的和 返回false
                        {return false;}else if(hasnum == 1) //旁边只有一个不为0的 中心数字与旁边数字同步减少
                        {int t = r[j];r[j] = 0;*((int *)M + has[0][0] * col + has[0][1]) -= t;}else if(r[j] == sum) //中心数字与旁边不为0的数字和相等
                        {for(int ii = 0; ii < hasnum; ii++){*((int *)M + has[ii][0] * col + has[ii][1]) = 0;}r[j] = 0;}}}}}}while(flag == true);return true;
}int main()
{int a[4][4] = {{0,1,0,0},{1,2,2,1},{0,1,3,0},{0,0,1,0}};bool f = canBeCreatedbyZero((int **)a, 4, 4);getchar();return 0;}

网上找答案:居然没有找到别人写好的代码。都是说个思路就完了!!

有说用最大流可以搞定 http://blog.csdn.net/lihappy999/article/details/7395934

有说匈牙利算法的

http://www.cnblogs.com/GoAhead/archive/2012/06/01/2531144.html 给了个方法 但我没看懂

最让我无语的是翻答案就得到这样一段话:

A assignment problem. Two ways to solve. 1: duplicate each cell to as many as its value,
do Hungarian algorithm. Denote the sum of the matrix as M, the edge number is 2M, so
the complexity is 2*M*M; 2: standard maximum flow. If the size of matrix is NxN, then the
algorithm using Ford Fulkerson algorithm is M*N*N.
too complex... I will do this when I have time...

【编程题目】对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一...相关推荐

  1. 2022-03-06:金币路径。 给定一个数组 A(下标从 1 开始)包含 N 个整数:A1,A2,……,AN 和一个整数 B。 你可以从数组 A 中的任何一个位置(下标为 i)跳到下标 i+1,i+

    2022-03-06:金币路径. 给定一个数组 A(下标从 1 开始)包含 N 个整数:A1,A2,--,AN 和一个整数 B. 你可以从数组 A 中的任何一个位置(下标为 i)跳到下标 i+1,i+ ...

  2. 算法训练 - 阿尔法乘积 计算一个整数的阿尔法乘积。对于一个整数x来说,它的阿尔法乘积是这样来计算的:如果x是一个个位数,那么它的阿尔法乘积就是它本身;否则的话,x的阿 尔法乘积就等于它的各位非0

    问题描述 计算一个整数的阿尔法乘积.对于一个整数x来说,它的阿尔法乘积是这样来计算的:如果x是一个个位数,那么它的阿尔法乘积就是它本身:否则的话,x的阿 尔法乘积就等于它的各位非0的数字相乘所得到的那 ...

  3. 输入一个字符串,内有数字和非数字字符,例如: A123x456 17960? 302tab5876 将其中连续的数字作为一个整数,依次存放到一数组a中。例如,123放在a[0],456放在a[1]……

    输入一个字符串,内有数字和非数字字符,例如: A123x456 17960? 302tab5876 将其中连续的数字作为一个整数,依次存放到一数组a中.例如,123放在a[0],456放在a[1]-- ...

  4. 习题 6.16 输入一个字符串,内有数字和非数字字符,例如: a123x456 17960? 302tab5876将其中连续的数字作为一个整数,依次存放到一数组a中。

    习题 6.16 输入一个字符串,内有数字和非数字字符,例如: a123x456 17960? 302tab5876将其中连续的数字作为一个整数,依次存放到一数组a中.例如,123存入在a[0],456 ...

  5. 输入一个字符串,内有数字和非数字字符,例如:A123x456 17960? 302tab5876,将其中连续的数字作为一个整数,依次存放到一数组a中。例如,123放在a[0],456放在a[1]...

    输入一个字符串,内有数字和非数字字符,例如:A123x456 17960? 302tab5876,将其中连续的数字作为一个整数,依次存放到一数组a中.例如,123放在a[0],456放在a[1]-统计 ...

  6. 【C】8.16输入一个字符串,内有数字和非数字字符,例如:A123x456 17960?302tab5876 ,将其中连续的数字作为一个整数,依次存放到一数组a中。例如:123放在a[0],456放在

    //输入一个字符串,内有数字和非数字字符,例如:A123x456 17960?302tab5876 //将其中连续的数字作为一个整数,依次存放到一数组a中. //例如:123放在a[0],456放在a ...

  7. 给定一个整数数组 nums 和一个整数目标值 target, 请你在该数组中找出和为目标值 target 的那两个整数, 并返回它们的数组下标

    题目要求: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标. [注]从前往后进行匹配, 一旦匹配成功, 便结 ...

  8. 【汇编语言与计算机系统结构笔记02】整数的计算机表示与运算,C中的无符号字符(unsigned)和带符号字符(signed),补码,一些例题

    本次笔记内容: 03.整数的计算机表示与运算 文章目录 预备知识 数制 数的机器表示 机器字在内存中的组织 字节序(Byte Ordering) 整数表示 计算机中整数的二进制编码方式 无符号数与带符 ...

  9. 已知:Sn= 1+1/2+1/3+…+1/n。显然对于任意一个整数K,当n足够大的时候,Sn大于K。 现给出一个整数K(k大于等于1小于等于15),要求计算出一个最小的n;使得Sn大于K。

    题目描述: 输入 键盘输入 k 输出屏幕输出 n样例输入 1样例输出 2 # include<stdio.h> int main() {int k,i;double Sn=0;scanf( ...

  10. 判断一个整数是否能被7整除或者数中含7

    #include <iostream> #include <algorithm> #include <string> #include <sstream> ...

最新文章

  1. C++和python先学哪个
  2. c++ 初始化 代码 应放在那里_Go语言goroutine调度器初始化 (12)
  3. TensorFlow2简单入门-三维张量
  4. dalvik虚拟机与Java区别_05 Android---java虚拟机跟dalvik虚拟机的区别(从01开始点点入门,视频+笔记)...
  5. yii+php+当前目录,Yii应用的目录结构和入口脚本
  6. 一文搞懂C语言回调函数
  7. 汇编语言-学习笔记(一)
  8. 长字符串显示引起的问题通用性解决方法
  9. 香港消委会:大部分航空公司超卖机票无赔偿细则
  10. GIF 字节格式介绍
  11. 深大uooc学术道德与学术规范教育第四章
  12. X99主板2011-3接口E5 CPU一览表
  13. vtop工具使用分析
  14. 如何安装OpenCVE
  15. adb 卸载android系统程序
  16. 什么是黑盒测试和白盒测试?
  17. 一般将来时语法课教案_一般将来时的被动语态语法课教学设计
  18. 手把手教你搭建明星脸相似度分析系统
  19. 计算机基础课小论文,计算机基础课程论文参考文献大全 哪里有计算机基础课程参考文献...
  20. ECharts Map 属性详解

热门文章

  1. 【C009】ArcGIS VBA - 学习
  2. 常见Sqlite管理工具
  3. ASV2011中文版本和英文版本的区别
  4. linux内核之中断和异常
  5. mysql数据库优化6_mysql数据库优化
  6. Wireshark实战分析之DHCP协议(二)
  7. php loadclass,Laravel如何实现自动加载类
  8. 解决:网络风暴引起的无法ping通
  9. JWT的Java使用 (JJWT)
  10. 电话聊天狂人(25 分)(散列函数)