算法学习——华为机考题库7(HJ41 - HJ45)
HJ41 称砝码
描述
现有n种砝码,重量互不相等,分别为 m1,m2,m3…mn ;
每种砝码对应的数量为 x1,x2,x3…xn 。现在要用这些砝码去称物体的重量(放在同一侧),问能称出多少种不同的重量。
注:
称重重量包括 0
数据范围:每组输入数据满足 1≤n≤10 , 1≤m ≤2000 , 1≤x i ≤10
输入描述:
对于每组测试数据:
第一行:n — 砝码的种数(范围[1,10])
第二行:m1 m2 m3 … mn — 每种砝码的重量(范围[1,2000])
第三行:x1 x2 x3 … xn — 每种砝码对应的数量(范围[1,10])
输出描述:
利用给定的砝码可以称出的不同的重量数
示例
代码解析
#include <iostream>
#include <set>
#include <vector>
using namespace std;
int main() {
int N;
cin>>N;
vector<int> weight;
vector<int> num;
vector<int> block;
int tmp;
for(int i=0 ; i<N ;i++)
{
cin>>tmp;
weight.push_back(tmp);
}
for(int i=0 ; i<N ;i++)
{
cin>>tmp;
num.push_back(tmp);
}
for(int i=0 ; i<N ;i++)
{
while(num[i]--)
block.push_back(weight[i]);
}
set<int> myset;
myset.insert(0);
for(int i=0 ; i<block.size() ;i++)
{
set<int> myset2(myset);
for(auto it:myset2)
myset.insert(it + block[i]);
}
// for(auto it:myset)
// cout<<it<<' ';
cout<<myset.size()<<endl;
}
// 64 位输出请用 printf("%lld")
HJ42 学英语
描述
Jessi初学英语,为了快速读出一串数字,编写程序将数字转换成英文:
具体规则如下:
1.在英语读法中三位数字看成一整体,后面再加一个计数单位。从最右边往左数,三位一单位,例如12,345 等
2.每三位数后记得带上计数单位 分别是thousand, million, billion.
3.公式:百万以下千以上的数 X thousand X, 10亿以下百万以上的数:X million X thousand X, 10 亿以上的数:X billion X million X thousand X. 每个X分别代表三位数或两位数或一位数。
4.在英式英语中百位数和十位数之间要加and,美式英语中则会省略,我们这个题目采用加上and,百分位为零的话,这道题目我们省略and
下面再看几个数字例句:
22: twenty two
100: one hundred
145: one hundred and forty five
1,234: one thousand two hundred and thirty four
8,088: eight thousand (and) eighty eight (注:这个and可加可不加,这个题目我们选择不加)
486,669: four hundred and eighty six thousand six hundred and sixty nine
1,652,510: one million six hundred and fifty two thousand five hundred and ten
说明:
数字为正整数,不考虑小数,转化结果为英文小写;
保证输入的数据合法
关键字提示:and,billion,million,thousand,hundred。
数据范围: 1≤n≤2000000
输入描述:
输入一个long型整数
输出描述:
输出相应的英文写法
示例
代码解析
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> other = {"zero", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen"};
vector<string> ften = {"none", "ten", "twenty", "thirty", "forty", "fifty", "sixty",
"seventy", "eighty", "ninety"};
string englishnum(long num)
{
if(num >= 0 && num <= 19) return other[num];
else if(num>=20 && num<=99)
{
if(num%10 == 0) return ften[num/10];
else return ften[num/10]+" "+englishnum(num%10);
}
else if(num>=100 && num<=999)
{
if(num%100 == 0) return other[num/100]+" hundred";
else return englishnum(num/100)+" hundred and "+ englishnum(num%100);
}
else if(num>=1000 && num<=999999)
{
if(num%1000 == 0) return englishnum(num/1000)+" thousand";
else return englishnum(num/1000)+" thousand "+englishnum(num%1000);
}
else if(num>=1000000&&num<=999999999)
{
if(num%1000000==0) return englishnum(num/1000000)+" million";
else return englishnum(num/1000000)+" million "+englishnum(num/1000%1000)+" thousand "+englishnum(num%1000);
}
else if(num>=1000000000)
{
if(num%1000000000==0) return other[num/1000000000]+" billion";
else return englishnum(num/1000000000)+" billion "+englishnum(num%10000000/1000000)+
" million "+englishnum(num%1000000/1000)+" thousand "+englishnum(num%1000);
}
return "";
}
int main()
{
long num;
cin>>num;
cout<<englishnum(num)<<endl;
}
// 64 位输出请用 printf("%lld")
HJ43 迷宫问题
描述
定义一个二维数组 N*M ,如 5 × 5 数组下所示:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线。入口点为[0,0],既第一格是可以走的路。
数据范围: 2≤n,m≤10 , 输入的内容只包含 0≤val≤1
输入描述:
输入两个整数,分别表示二维数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。
输出描述:
左上角到右下角的最短路径,格式如样例所示。
示例
代码解析
#include <climits>
#include <iostream>
#include <utility>
#include <vector>
using namespace std;
int n,m;
int fornt[4][2] = {-1,0,1,0,0,-1,0,1};
vector<vector<vector<int>>> result2;
void dfs(vector<vector<int>> &date , vector<vector<bool>> &path , vector<vector<int>> &result , int x , int y)
{
if(path[x][y] == true) return;
path[x][y] = true;
if(date[x][y] == 1) return;
if(x == n-1 && y == m-1) result2.push_back(result);
int new_x , new_y;
for(int i=0 ; i < 4 ; i++)
{
new_x = x + fornt[i][0];
new_y = y + fornt[i][1];
if( new_x < 0 || new_x >= n || new_y < 0 || new_y >= m) continue;
result.push_back({new_x,new_y});
dfs(date,path,result,new_x,new_y);
result.pop_back();
}
return ;
}
int main() {
int tmp;
cin>>n>>m;
vector<vector<int>> date(n,vector<int>(m,0));
vector<vector<int>> result;
vector<vector<bool>> path(n,vector<bool>(m,false));
for(int i=0 ; i<n ; i++)
{
for(int j=0 ; j<m ; j++)
{
cin>>tmp;
date[i][j] = tmp;
}
}
result.push_back({0,0});
dfs(date,path,result,0,0);
pair<int, int> minResult = {INT_MAX,INT_MAX};
for(int i=0 ; i<result2.size() ; i++)
{
if(result2[i].size() < minResult.second)
{
minResult.first = i;
minResult.second = result2[i].size();
}
}
for(int i=0 ; i< minResult.second ; i++)
{
cout<<'('<<result2[minResult.first][i][0]<<","<<result2[minResult.first][i][1]<<")"<<endl;
}
}
// 64 位输出请用 printf("%lld")
HJ44 Sudoku
描述
问题描述:数独(Sudoku)是一款大众喜爱的数字逻辑游戏。玩家需要根据9X9盘面上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个3X3粗线宫内的数字均含1-9,并且不重复。
例如:
输入
输出
数据范围:输入一个 9*9 的矩阵
输入描述:
包含已知数字的9X9盘面数组[空缺位以数字0表示]
输出描述:
完整的9X9盘面数组
示例
代码解析
#include <iostream>
#include <set>
#include <vector>
using namespace std;
bool flag = false;
bool cheack(vector<vector<int>> &date , int x , int y ,int value)
{
//行
for(int j=0 ; j<9 ; j++)
{
if( date[x][j] == value ) return false;
}
//列
for(int j=0 ; j<9 ; j++)
{
if( date[j][y] == value) return false;
}
//块
int newx = x - x%3;
int newy = y - y%3;
for(int n = newx ; n < newx + 3 ; n++)
{
for(int m = newy ; m < newy + 3 ; m++)
{
if( date[n][m] == value) return false;
}
}
return true;
}
void dfs(vector<vector<int>> &date , int x , int y)
{
//cout<<x<<' '<<y<<" date:"<<date[x][y]<<endl;
if(date[x][y] != 0)
{
if(x==8 && y==8)
{
flag = true;
return;
}
if(y != 8) dfs(date,x,y+1);
else dfs(date,x+1,0);
return;
}
// cout<<x<<' '<<x<<' '<<date[x][y]<<endl;
for(int i=1 ; i<=9 ; i++)
{
if(cheack(date, x, y, i) == true)
{
date[x][y] = i;
if(x==8 && y==8)
{
flag = true;
return;
}
if(y != 8) dfs(date,x,y+1);
else dfs(date,x+1,0);
if(flag == false) date[x][y] = 0;
}
}
}
int main() {
vector<vector<int>> date(9,vector<int>(9,0));
int tmp;
for(int i=0 ; i<9 ;i++)
{
for(int j=0 ; j<9 ;j++)
{
cin>>tmp;
date[i][j] = tmp;
}
}
dfs(date, 0, 0);
for(int i=0 ; i<9 ;i++)
{
for(int j=0 ; j<9 ;j++)
{
cout<<date[i][j]<<' ';
}
cout<<endl;
}
}
// 64 位输出请用 printf("%lld")
HJ45 名字的漂亮度
描述
给出一个字符串,该字符串仅由小写字母组成,定义这个字符串的“漂亮度”是其所有字母“漂亮度”的总和。
每个字母都有一个“漂亮度”,范围在1到26之间。没有任何两个不同字母拥有相同的“漂亮度”。字母忽略大小写。
给出多个字符串,计算每个字符串最大可能的“漂亮度”。
本题含有多组数据。
数据范围: 输入的名字长度满足 1≤n≤10000
输入描述:
第一行一个整数N,接下来N行每行一个字符串
输出描述:
每个字符串可能的最大漂亮程度
示例
代码解析
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <utility>
#include <vector>
using namespace std;
int beatiful(string &str)
{
map<char, int> mymap;
for(auto it:str)
mymap[it]++;
vector<pair<char,int>> vec(mymap.begin() , mymap.end());
sort(vec.begin(), vec.end() , [](pair<char, int> &p1 , pair<char, int> &p2){return p1.second > p2.second;});
int value = 26;
for(int i=0 ; i<vec.size() ; i++)
{
vec[i].second = value;
value--;
}
int result = 0;
for(auto it:str)
{
for(auto it2 : vec)
{
if(it == it2.first)
{
result += it2.second;
break;
}
}
}
return result;
}
int main() {
int N;
cin>>N;
vector<string> date;
string tmp;
while(N--)
{
cin>>tmp;
date.push_back(tmp);
}
for(auto it:date)
cout<<beatiful(it)<<endl;
}
// 64 位输出请用 printf("%lld")