【编程题目】对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一...
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...
【编程题目】对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一...相关推荐
- 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+ ...
- 算法训练 - 阿尔法乘积 计算一个整数的阿尔法乘积。对于一个整数x来说,它的阿尔法乘积是这样来计算的:如果x是一个个位数,那么它的阿尔法乘积就是它本身;否则的话,x的阿 尔法乘积就等于它的各位非0
问题描述 计算一个整数的阿尔法乘积.对于一个整数x来说,它的阿尔法乘积是这样来计算的:如果x是一个个位数,那么它的阿尔法乘积就是它本身:否则的话,x的阿 尔法乘积就等于它的各位非0的数字相乘所得到的那 ...
- 输入一个字符串,内有数字和非数字字符,例如: A123x456 17960? 302tab5876 将其中连续的数字作为一个整数,依次存放到一数组a中。例如,123放在a[0],456放在a[1]……
输入一个字符串,内有数字和非数字字符,例如: A123x456 17960? 302tab5876 将其中连续的数字作为一个整数,依次存放到一数组a中.例如,123放在a[0],456放在a[1]-- ...
- 习题 6.16 输入一个字符串,内有数字和非数字字符,例如: a123x456 17960? 302tab5876将其中连续的数字作为一个整数,依次存放到一数组a中。
习题 6.16 输入一个字符串,内有数字和非数字字符,例如: a123x456 17960? 302tab5876将其中连续的数字作为一个整数,依次存放到一数组a中.例如,123存入在a[0],456 ...
- 输入一个字符串,内有数字和非数字字符,例如:A123x456 17960? 302tab5876,将其中连续的数字作为一个整数,依次存放到一数组a中。例如,123放在a[0],456放在a[1]...
输入一个字符串,内有数字和非数字字符,例如:A123x456 17960? 302tab5876,将其中连续的数字作为一个整数,依次存放到一数组a中.例如,123放在a[0],456放在a[1]-统计 ...
- 【C】8.16输入一个字符串,内有数字和非数字字符,例如:A123x456 17960?302tab5876 ,将其中连续的数字作为一个整数,依次存放到一数组a中。例如:123放在a[0],456放在
//输入一个字符串,内有数字和非数字字符,例如:A123x456 17960?302tab5876 //将其中连续的数字作为一个整数,依次存放到一数组a中. //例如:123放在a[0],456放在a ...
- 给定一个整数数组 nums 和一个整数目标值 target, 请你在该数组中找出和为目标值 target 的那两个整数, 并返回它们的数组下标
题目要求: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标. [注]从前往后进行匹配, 一旦匹配成功, 便结 ...
- 【汇编语言与计算机系统结构笔记02】整数的计算机表示与运算,C中的无符号字符(unsigned)和带符号字符(signed),补码,一些例题
本次笔记内容: 03.整数的计算机表示与运算 文章目录 预备知识 数制 数的机器表示 机器字在内存中的组织 字节序(Byte Ordering) 整数表示 计算机中整数的二进制编码方式 无符号数与带符 ...
- 已知: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( ...
- 判断一个整数是否能被7整除或者数中含7
#include <iostream> #include <algorithm> #include <string> #include <sstream> ...
最新文章
- C++和python先学哪个
- c++ 初始化 代码 应放在那里_Go语言goroutine调度器初始化 (12)
- TensorFlow2简单入门-三维张量
- dalvik虚拟机与Java区别_05 Android---java虚拟机跟dalvik虚拟机的区别(从01开始点点入门,视频+笔记)...
- yii+php+当前目录,Yii应用的目录结构和入口脚本
- 一文搞懂C语言回调函数
- 汇编语言-学习笔记(一)
- 长字符串显示引起的问题通用性解决方法
- 香港消委会:大部分航空公司超卖机票无赔偿细则
- GIF 字节格式介绍
- 深大uooc学术道德与学术规范教育第四章
- X99主板2011-3接口E5 CPU一览表
- vtop工具使用分析
- 如何安装OpenCVE
- adb 卸载android系统程序
- 什么是黑盒测试和白盒测试?
- 一般将来时语法课教案_一般将来时的被动语态语法课教学设计
- 手把手教你搭建明星脸相似度分析系统
- 计算机基础课小论文,计算机基础课程论文参考文献大全 哪里有计算机基础课程参考文献...
- ECharts Map 属性详解