题目

给定一个 n*m 的矩阵 A ,矩阵中每一个元素为一个十六进制数。寻找一条从左上角都右下角的路径,每次只能向右或者向下移动, 
使得路径上所有数字之积在 16 进制下的后缀 0 最少。

输入描述:

第一行:n, m (2 <= n,m <= 1000) 
接下来 n 行,每行 m 个 16 进制整数 0<=aij<=1090<=aij<=109

输出描述:

第一行:最少后缀 0 的个数(十进制) 
第二行:路径方案,从左上角开始,”>” 代表向右移动,”V” 代表向下移动。 
如果有多种方案,输出字典序最小的方案(“>” 的字典序小于 “V”)。

示例:
  • 输入

    3 3 
    3 2 8 
    c 8 8 
    2 a f

  • 输出


    ‘>>VV’(此处输出实际上没有引号)

  • 说明 
    从左上角到右下角的所有路径中, 0x3 * 0x2 * 0x8 * 0x8 * 0xf = 0x1680 后缀 0 最少为 1, 且路径 “>>VV” 的字典序最小。

思路

  • 首先需要设计一个函数来判断十六进制数字末尾零的个数。可以分为两种情况,小于 16 的数只有 0 末尾有一个零;大于等于 16 的数如果最后一位是 0,则肯定可以被 16 整除,若末尾是 0,我们对这个十六进制数向右移一位,也即除以 16,再看倒数第二位是否是零,这样一直往前判断直到某一位非零为止。

  • 路径判断则用动态规划来实现。定义两个变量,第一个变量保存从左上角到每一个位置处的乘积,第二个变量保存是怎样从前一步到当前位置的,只有向右或者向下两种情况,用枚举表示。第一行只能向右走,第一列只能向下走,这是初始化情况。然后从第二行第二列开始进行判断,每一步比较从左边来的乘积和从上边来的乘积末尾含有零的个数,若二者不相等,则保存乘积和移动方向到相应变量中。若向下和向右二者相等,则需要分别向上和向左回溯到左上角倒序求出移动方向,然后从头开始比较,选择字典序小的路径作为最终的移动方向。

样例展示 (从左到右分别是原始数字、十六进制乘积和移动方向)

3 o 2 (6) (>) 8 (30) (>)
c (24) (V) 8 (30) (V) 8 (180) (V)
2 (48) (V) a (1E0) (V) f (1680) (V)

第二行第二个位置,从左边来是 24×8 = 120,末尾有 1 个 0;从上边来是 6×8 = 30,也有 1 个 0。 
从左边来路径是 V>,从右边来路径是 >V,由于 > 字典序小于 V,因此最终移动方向为 >V。

代码实现

#include <iostream>
#include <vector>
using namespace std; int find_zero_num(int number);
int min_dictionary(int *direction, int i, int j, int col);
void find_route(int *direction, vector<int> &route, int m, int n, int col); enum {RIGHT = , DOWN = }; //向下走为 1 ,向右走为 0 int main()
{
int n = , m = ;
cin >> n >> m; int data[n][m];
//保存矩阵中的数据
long int product[n][m];
//保存从左上角到位置(i, j)处的乘积
int direction[n][m] = {};
//保存位置(i, j)处的乘积是怎么得到的,1为从前一位置往下,0为从前一位置往右 vector<int> route; //倒序保存路径 int i = , j = ; for(i = ; i < n ; i++)
{
for(j = ; j < m; j++)
{
cin >> hex >> data[i][j];
}
} // 初始化第一列的乘积作为边界值
product[][] = data[][];
for(i = ; i < n; i++)
{
product[i][] = product[i-][] * data[i][];
direction[i][] = DOWN;
} // 初始化第一行的乘积作为边界值
for(j = ; j < m; j++)
{
product[][j] = product[][j-] * data[][j];
direction[][j] = RIGHT;
} long int down = ;
long int right = ;
int flag = ; for(i = ; i < n; i++)
{
for (j = ; j < m; j++)
{
down = product[i-][j] * data[i][j]; //往下走的乘积
right = product[i][j-] * data[i][j]; //往右走的乘积 if (find_zero_num(down) < find_zero_num(right))
{
flag = ;
}
else if (find_zero_num(down) > find_zero_num(right))
{
flag = RIGHT;
}
else //若向下和向右一样,则优先取字典序小的
{
if(min_dictionary(*direction, i, j, m))
{
flag = DOWN;
}
else
{
flag = RIGHT;
}
} if(!flag)
{
product[i][j] = right;
direction[i][j] = RIGHT;
}
else
{
product[i][j] = down;
direction[i][j] = DOWN;
}
}
} cout << find_zero_num(product[n-][m-]) << endl; find_route(*direction, route, n-, m-, m); for(i = int(route.size()-); i >= ; i--)
{
if (route[i])
{
cout << 'V';
}
else
{
cout << '>';
}
} return ;
} // find the zero number of a hex data
int find_zero_num(int number)
{
int sum = ;
if(number == )
{
sum = ;
}
while (number % == && number >= )
{
sum++;
number = number / ;
}
return sum;
} int min_dictionary(int *direction, int i, int j, int col)
{
vector<int> route_down;
vector<int> route_right; int m = i - ;
int n = j;
find_route(direction, route_down, m, n, col); //向上回溯路线 m = i;
n = j - ;
find_route(direction, route_right, m, n, col); //向左回溯路线 int length = int(route_right.size()); for (i = length - ; i >= ; i--) //从第一个不相等的位置处开始判断字典序
{
if (route_right[i] < route_down[i])
{
return ; //向右字典序小
}
if (route_right[i] > route_down[i])
{
return ; //向下字典序小
}
} return -;
} // 从位置 (m, n) 处回溯路线,倒序保存在向量中
void find_route(int *direction, vector<int> &route, int m, int n, int col)
{
while()
{
// 此位置乘积由上一位置向下移动得来,行数减一继续寻找
if(direction[m * col + n] == )
{
m = m - ;
route.push_back();
}
// 此位置乘积由上一位置向右移动得来,列数减一继续寻找
else
{
n = n - ;
route.push_back();
} // 寻找至左上角,结束
if (m == && n == )
{
break;
}
}
}

个人见解,如有错误,欢迎指正与交流!

获取更多精彩,请关注「seniusen」! 

今日头条 2018 AI Camp 5 月 26 日在线笔试编程题第一道——最佳路径的更多相关文章

  1. 今日头条 2018 AI Camp 5 月 26 日在线笔试编程题第二道——最小分割分数

    题目: 给 n 个正整数 a_1,…,a_n, 将 n 个数顺序排成一列后分割成 m 段,每一段的分数被记为这段内所有数的和,该次分割的分数被记为 m 段分数的最大值.问所有分割方案中分割分数的最小值 ...

  2. 今日头条 2018 AI Camp 6 月 2 日在线笔试编程题第一道——最大连续区间和扩展

    题目 给出一个长度为 n 的数组a1.a2.....ana1.a2.....an,请找出在所有连续区间 中,区间和最大同时这个区间 0 的个数小于等于 3 个,输出这个区间和. 输入描述: 第一行一个 ...

  3. 今日头条 2018 AI Camp 6 月 2 日在线笔试编程题第二道——两数差的和

    题目 给 n 个实数 a_1, a_2 ... a_n, 要求计算这 n 个数两两之间差的绝对值下取整后的和是多少. 输入描述 第一行为一个正整数 n 和一个整数 m.接下来 n 行,第 i 行代表一 ...

  4. 今日头条 2018 AI Camp 视频面试

    1. 本次面试是在牛客网平台进行的,没有涉及到技术细节,面试官也说仅仅是聊天.但是,不知道是网络卡顿还是平台缘故,连接非常不稳定,经常听不到声音,对方那边噪音也特别大,面试体验不是很好. 2. 面试时 ...

  5. 链家2018春招C/C++开发实习生在线考试编程题

    题目一 题解:该题目意思就是让你输入n组数据,然后求并集,利用STL容器set集合的特性:元素不重复存储,我们可以很轻易得出答案 #include <iostream> #include ...

  6. [转帖]ARM A77+G77最强公版架构:联发科5G SoC计划11月26日发布

    ARM A77+G77最强公版架构:联发科5G SoC计划11月26日发布 https://www.cnbeta.com/articles/tech/909025.htm 主流的手机SoC厂商已经纷纷 ...

  7. 2016年12月26日 星期一 --出埃及记 Exodus 21:21

    2016年12月26日 星期一 --出埃及记 Exodus 21:21 but he is not to be punished if the slave gets up after a day or ...

  8. 10月26日 奥威Power-BI基于微软示例库(MSOLAP)快速制作管理驾驶舱 腾讯课堂开课啦

    本次课是基于olap数据源的案例实操课,以微软olap示例库Adventure Works为数据基础.        AdventureWorks示例数据库为一家虚拟公司的数据,公司背景为大型跨国生产 ...

  9. 2016年11月26日 星期六 --出埃及记 Exodus 20:17

    2016年11月26日 星期六 --出埃及记 Exodus 20:17 "You shall not covet your neighbor's house. You shall not c ...

随机推荐

  1. 如果有人问你CAP理论是什么,就把这篇文章发给他。

    绝对和你在网上看到的CAP定理介绍不一样. CAP 定理(CAP theorem)又被称作布鲁尔定理(Brewer's theorem),是加州大学伯克利分校的计算机科学家埃里克·布鲁尔(Eric B ...

  2. Python 学习笔记(十一)Python语句(一)

    运算符和条件语句 算术运算符 运算符 描述 实例 + 加 - 两个对象相加 a + b 输出结果 30 - 减 - 得到负数或是一个数减去另一个数 a - b 输出结果 -10 * 乘 - 两个数相乘 ...

  3. ORCLE10安装常见配置问题-oui.exe停止工作

    其实这是一个在安装过程中很常见的问题,之前小编说过关于甲骨文的软件用起来都很强大,但是大腕出厂,出场费是很高的,就像甲骨文的软件使用的话对于他的安装和配置的换将也是很挑剔的,出现这个问题就是因为安装文 ...

  4. MySQL---下载安装、数据库基本操作

    1.下载安装 1.1 下载:  http://dev.mysql.com/downloads/mysql/ 1.2 解压 1.3 初始化 cd c:\mysql-5.7.16-winx64\bin ( ...

  5. vue 新属性学习

    1, $listeners 父级元素 <base-input v-on:focus.native="onFocus"></base-input> 子级元素 ...

  6. 关于PHPExcel 导出下载表格,调试器响应乱码

    PHPExcel导出表格是日常程序开发很常见的一功能,有些小伙伴千辛万苦把代码写好之后,运行一下结果发现浏览器没反应,表格下载不了或者表格乱码!!!像这种情况有三种解决方法: 1.在header 之前 ...

  7. Django搭配Celery进行异步/定时任务(一)初步搭建

    以下需求场景很常见: 1. 用户点击页面按钮,请求后台进行一系列耗时非常高的操作,页面没有响应/一直Loading,用户体验非常不好. 2. 某些数据需要预先处理,每天凌晨的时候进行运算,大约半小时到 ...

  8. 通过burpsuite替换cookie登录后台

    通过burpsuite可以比较方便的替换http头部的cookie.useragent等字段,在获取到用户的cookie后实现登录.具体使用方法如下: 如替换cookie,可以写正则表达式^Cooki ...

  9. 在window10平台下安装TensorFlow(only cpu)

    这是我在安装tensorflow遇到的问题记录 希望可以给大家一些帮助(2019年1月6日) 1. 需要安装的环境及软件 python3.6 Anaconda Tensorflow 2. 先安装ana ...

  10. 实验6 shell程序设计一(2)

    编写一段bash shell程序, 根据键盘输入的学生成绩,显示相应的成绩登等级, 其中 60分以下为"Failed!", 60-69分为"Passed!", ...