观前提醒:
笔试所有系列文章均是记录本人的笔试题思路与代码,从中得到的启发和从别人题解的学习到的地方,所以关于题目的解答,只是以本人能读懂为目标,如果大家觉得看不懂,那是正常的。如果对本文的某些知识有不同的观点,欢迎讨论。
题目链接:
第一题:牛牛的快递_牛客题霸_牛客网
第二题:最小花费爬楼梯_牛客题霸_牛客网
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
第一题
思路:
本题就是一道简单的模拟题,可能存在的较难点是,如何将小数向上取整,这里有两种方法
1)使用c语言自带的ceil函数,它的功能就是向上取整,但是一般情况下,很难想到。
2)将浮点数转换为整型,然后再与原始值相减,观察结果。
代码:
//ceil库函数版本
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double a=0;
char b;
cin>>a>>b;
int coin=0;
if(a>1)
{
coin+=(20+ceil(a-1));
}
else {
coin+=20;
}
if(b == 'y') coin+=5;
printf("%d\n",coin);
return 0;
}
//使用类型强转版本
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double a=0;
char b;
cin>>a>>b;
int coin=0;
coin+=20; //因为a一定大于0,一定要加上这20元。
if(a>1)
{
double c=a-1;
if(c >(int)c) coin+=((int)c+1);
else
coin+=(c);
}
if(b == 'y') coin+=5;
printf("%d\n",coin);
return 0;
}
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
第二题
思路:
题目第一眼,一道简单的动态规划题,可能最需要解释的是题意,题目要求到达楼顶,说明走过了所有的台阶,所以要返回到达n+1台阶后的花费的价钱。
状态表示:一个一维的dp表,表中内容为:到现在的台阶,花费的最小价格。
状态转移方程:假如现在求dp[n],dp[n]只能由dp[n-2]和dp[n-1]跳上来,两种跳上来的方案选择价格最少的就好了,需要注意的是跳上来的同时还要考虑本次起跳的花费
代码:
#include <iostream>
#include<vector>
using namespace std;
int main() {
int n=0;
cin>>n;
vector<int> cost(n),dp(n+1,0);
//dp[n]就是跳过所有的台阶,到达的楼顶。
for(int i=0;i<n;i++)
{
int x=0;
cin>>x;
cost[i]=x;
}
for(int i=2;i<=n;i++)
{
dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
}
printf("%d\n",dp[n]);
return 0;
}
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
---------------------------------------------------我是分割线---------------------------------------------------------------
第三题
思路:
1)暴力枚举
看到题目的反映是,求距离那就要考虑数组的下标,求下标的最简单方法是,双重遍历考虑所有的情况,但是时间复杂度太高,为O(n2),面对最高到10^5的数据要超时,那我们就要想其他办法。
2)贪心
我们想到我们可以通过哈希表记录下所有的目标字符的下标,但是通过示例二发现数组中可能有多个目标字符,所有要使用int数组记录所有的下标,然后再遍历哈希表。
但是我们又想到,既然已经要使用两个元素大小的哈希表,为啥不直接选择两个变量记录下标呢?每次下标更新,就更新距离(这就演变成了贪心,贪婪的地方在于我们每次考虑距离的时候,只是考虑前面的目标产生的距离)。
想要求的距离最短,所以选择min函数,因此要将记录距离的变量初始化一个较大的值。
代码:
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int main() {
int ret=0x3f3f3f3f;
//对应下面的min函数
int len=0;
cin>>len;
//这里没有必要真的记录下字符数组,反正也只是考虑数组的下标关系
if(len == 1 )
{
printf("-1\n");
return 0;
}
string str1="",str2="";
cin>>str1>>str2;
int cur1=-1,cur2=-1;
//将记录目标字符的初始下标设为-1,是为了防止目标字符不在字符数组当中。
//当然也是为了保证ret记录的距离是有效值。
string str3="";
for(int i=0;i<len;i++)
{
cin>>str3;
if(str3 == str1)
cur1=i;
if(str3 == str2)
cur2=i;
if(cur2 != cur1 && cur1 != -1 && cur2 != -1)
{
ret=min(ret,abs(cur2-cur1));
}
// printf("1\n");
}
//特殊判断,如果目标字符不在字符数组当中
printf("%d\n",ret == 0x3f3f3f3f ?-1:ret);
return 0;
}