题目

给定一个 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. Can't connect to X11 window server using 'localhost:10.0' as the value of the DISPLAY variable.

    刚刚在一台Linux服务器上安装了jdk和Tomcat,然后部署了一个web项目,在项目中有个添加图片的功能,保存图片时报错 org.springframework.web.util.NestedSe ...

  2. 开发类似"音速启动"的原创工具简码"万能助手"的过程中对ztree.js与win标准控件treeview、HTMLayout树形框等优缺点的比较

    在开发类似"音速启动"的桌面快捷方式管理软件简码"万能助手"的早期规划中,曾经考虑过几种树形框方案: ztree.js.win标准控件treeview.HTML ...

  3. Mysql存储引擎myisam与inndb的区别?

    最近在研究Mysql存储引擎这块,说白了就是如何存储数据.如何为存储的数据建立索引和如何更新.查询数据等技术的实现方法,在此做一个大概总结: 其实在工作中用的最多也就是MYISAM和INNODB,IN ...

  4. rz/sz:工作原理

    我们知道用linux命令rz/sz可以通过一些终端软件如secureCRT等在linux服务器与本地windows之间传文件.在服务器上rz一下,在本地windows下就跳出一个窗口,选择文件后就传到 ...

  5. layer 刷新某个页面

    一:使用layer.open打开的子页面 window.parent.location.reload()//刷新父页面 var index = parent.layer.getFrameIndex(w ...

  6. 内网环境下为Elasticsearch 5.0.2 添加head服务

    背景: 本项目的服务器是内网环境,没有网络,因此需要在离线的环境中,安装head服务. 需要用到的安装包有: node的安装包 elasticsearch的head插件源码 说明:此次只讲述为elas ...

  7. 面试乐融集团Python开发工程师有感

    这是笔者第一次面试,,乐融集团位于朝阳区朝阳公园的乐融大厦.是下午两点的笔面试,笔者是一点半到的,然后在里面等了会,开始笔试 笔试题并不是太难,就是考的比较宽,因为笔者是校招,所以笔试题出来了数据结构 ...

  8. python代理爬取存入csv文件

    爬取高匿代理 from urllib import request import re import time f = open('西1.csv','w',encoding='GBK') header ...

  9. 创建IDataProvider实例

    using System; namespace Demo.Data{ public class DatabaseProvider { private static IDataProvider _ins ...

  10. ACM数论-素数

    ACM数论——素数  素数定义: 质数(prime number)又称素数,有无限个.质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数,这样的数称为质数.例 子:2.3.5.7.11.1 ...