今日头条 2018 AI Camp 5 月 26 日在线笔试编程题第一道——最佳路径
题目
给定一个 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输出
1
‘>>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 日在线笔试编程题第一道——最佳路径的更多相关文章
- 今日头条 2018 AI Camp 5 月 26 日在线笔试编程题第二道——最小分割分数
题目: 给 n 个正整数 a_1,…,a_n, 将 n 个数顺序排成一列后分割成 m 段,每一段的分数被记为这段内所有数的和,该次分割的分数被记为 m 段分数的最大值.问所有分割方案中分割分数的最小值 ...
- 今日头条 2018 AI Camp 6 月 2 日在线笔试编程题第一道——最大连续区间和扩展
题目 给出一个长度为 n 的数组a1.a2.....ana1.a2.....an,请找出在所有连续区间 中,区间和最大同时这个区间 0 的个数小于等于 3 个,输出这个区间和. 输入描述: 第一行一个 ...
- 今日头条 2018 AI Camp 6 月 2 日在线笔试编程题第二道——两数差的和
题目 给 n 个实数 a_1, a_2 ... a_n, 要求计算这 n 个数两两之间差的绝对值下取整后的和是多少. 输入描述 第一行为一个正整数 n 和一个整数 m.接下来 n 行,第 i 行代表一 ...
- 今日头条 2018 AI Camp 视频面试
1. 本次面试是在牛客网平台进行的,没有涉及到技术细节,面试官也说仅仅是聊天.但是,不知道是网络卡顿还是平台缘故,连接非常不稳定,经常听不到声音,对方那边噪音也特别大,面试体验不是很好. 2. 面试时 ...
- 链家2018春招C/C++开发实习生在线考试编程题
题目一 题解:该题目意思就是让你输入n组数据,然后求并集,利用STL容器set集合的特性:元素不重复存储,我们可以很轻易得出答案 #include <iostream> #include ...
- [转帖]ARM A77+G77最强公版架构:联发科5G SoC计划11月26日发布
ARM A77+G77最强公版架构:联发科5G SoC计划11月26日发布 https://www.cnbeta.com/articles/tech/909025.htm 主流的手机SoC厂商已经纷纷 ...
- 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 ...
- 10月26日 奥威Power-BI基于微软示例库(MSOLAP)快速制作管理驾驶舱 腾讯课堂开课啦
本次课是基于olap数据源的案例实操课,以微软olap示例库Adventure Works为数据基础. AdventureWorks示例数据库为一家虚拟公司的数据,公司背景为大型跨国生产 ...
- 2016年11月26日 星期六 --出埃及记 Exodus 20:17
2016年11月26日 星期六 --出埃及记 Exodus 20:17 "You shall not covet your neighbor's house. You shall not c ...
随机推荐
- 『ACM C++』 PTA 天梯赛练习集L1 | 050-51
加油加油,努力刷题 ------------------------------------------------L1-050------------------------------------ ...
- 『C++』Temp_2018_12_06
#include <iostream> #include <string> using namespace std; class Type{ public: string Na ...
- 模板——最小生成树prim算法&&向前星理解
通过最小生成树(prim)和最短路径优化引出的向前星存图,时至今日才彻底明白了.. head[i]存储的是父节点为i引出的最后一条边的编号, next负责把head[i]也就是i作为父节点的所有边连接 ...
- Zabbix——部署(agent和proxy安装)
前提条件: 已经完成对Zabbix-server的安装 已经完成对Mysql的安装 并且相互和正常使用和访问 配置agent服务器: rpm -Uvh https://repo.zabbix.com/ ...
- MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述 # Time: :: # User@Host: **[**] @ [**] Id: ** # Killed: # Query_time: Rows_examined: Rows_affect ...
- ubuntu下安装memcached和PHP的memcache扩展
依赖包和软件包下载地址: Libevent:https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/li ...
- ACM 2003~2005
ACM 2003 求实数的绝对值 import java.util.Scanner; public class Lengxc { public static void main(String[] ar ...
- thinkphp5 toArray()报错
//DB操作返回是数组.模型直接操作返回是对象 //对象类型转换数组 //打开 database.php 增加或修改参数 'resultset_type' => '\think\Collecti ...
- Dubbo client 启动报错:No provider available for the service use dubbo version 2.5.3
1.异常 java.lang.IllegalStateException: Failed to check the status of the service org.ko.server.servic ...
- hadoop jobhistory访问界面长时间打不开
1.浏览器无法直接通过url访问 可能原因 :主机名未配置,因此无法识别,在 c:\windows\system32\drivers\etc 目录添加主机名和对应ip hostname1[主机名 ] ...