算法1111
文章目录
- 1. 牛牛的快递
- 1.1 思路
- 1.2 源码
- 1.3总结
- 2. 最小花费爬楼梯
- 2.1 思路
- 2.2 源码
- 3. 数组中两个字符串的最小距离
- 3.1 思路
- 3.2 源码
- 3.2.1 第一遍
- 3.2.2 第二遍
- 3.3 总结
1. 牛牛的快递
牛牛的快递
1.1 思路
一道简单的模拟题
1.2 源码
#include <iostream>
using namespace std;
#include<cmath>int main() {float w;char ch;int ret = 0;cin >> w >> ch;if (w <= 1)ret += 20;else {ret += 20;w -= 1;ret += ceil(w);}if (ch == 'y')ret += 5;cout << ret << endl; return 0;
}
1.3总结
cout << ret << endl;要加endl,刷新一下缓冲区,不加过不了。- 用了ceil向上取整函数。
2. 最小花费爬楼梯
最小花费爬楼梯
2.1 思路
经典的动态规划
- 确定状态表示:dp[i] 表示到达i位置时的最小花费。
- 确定状态转移方程:
min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]) - 填表顺序:从左向右
- 初始化:dp[0] = 0, dp[1] = 0
- 返回dp[n]
2.2 源码
#include<iostream>
#include<cstring>/*
描述
给定一个整数数组 cost ,其中 cost[i] 是从楼梯第i 个台阶向上爬需要支付的费用,下标从0开始。
一旦你支付此费用,即可选择向上爬一个或者两个台阶。
*/
using namespace std;
const int MAXN = 100000 + 1;
int cost[MAXN];
int dp[MAXN];//手写分析过程:
//从大到小分析 对于第 i 阶,到顶需要的花费 dp[i] = cost[i] + min(dp[i + 1] , dp[i + 2])
//最后取 min(dp[0] , dp[1])
int main() {int n;cin >> n;for (int i = 0; i < n; ++i) {cin >> cost[i];}if (n == 1) {cout << cost[0] << endl;return 0;} else if (n == 2) {cout << min(cost[0], cost[1]);return 0;} else {memset(dp, 0, sizeof(dp));//dp初始化 对于最后一阶和倒数第二阶而言,他们需要的花费就是他们位置的costdp[n - 1] = cost[n - 1];dp[n - 2] = cost[n - 2];//从单数第三个开始,花费 就是 cost[i] + min(dp[i + 1] , dp[i + 2])//跳一步 和 跳两步 两种情况取花费少的情况for (int i = n - 3; i >= 0; --i) {dp[i] = cost[i] + min(dp[i + 1], dp[i + 2]);}//最后从“从0开始”和“从1开始” 两者选小的那个//实际上,二者表达的是 从0 、1开始之后的能实现的最低花费已经计算出来了//选择只是为了选择 “从哪个开始更优”cout << min(dp[0], dp[1]) << endl;}return 0;
}
3. 数组中两个字符串的最小距离
数组中两个字符串的最小距离
3.1 思路
- 暴力解法(双指针遍历数组)
- 优化暴力解法(一个指针,两个变量,一次循环遍历解决问题)
- 预处理的思想,不再用指针遍历,而是用变量存储。
3.2 源码
3.2.1 第一遍
#include <iostream>
using namespace std;
#include <vector>
#include <string>
#include <cstdlib>int main()
{int n = 0;cin >> n;vector<string> strs;for (int i = 0; i < n; i++) {string str;cin >> str;strs[i] = str;}string str1, str2;cin >> str1 >> str2;int prev1, prev2;prev1 = prev2 = -1;int ret = 0;for (int i = 0; i < n; i++) {if (strs[i] == str1) {prev1 = i;if(strs[prev2] == str2)ret = prev1 - prev2;}else if (strs[i] == str2) {prev2 = i;if(strs[prev1] == str1)ret = prev1 - prev2;}}cout << abs(ret) << endl;return 0;
}
3.2.2 第二遍
#include<iostream>
#include<string>
using namespace std;int main() {int n;string s;string s1, s2;cin >> n;cin >> s1 >> s2;int prev1 = -1, prev2 = -1, ret = 0x3f3f3f3f;for (int i = 0; i < n; i++) {cin >> s;if (s == s1) {if (prev2 != -1)ret = min(ret, i - prev2);prev1 = i;}if (s == s2) {if (prev1 != -1)ret = min(ret, i - prev1);prev2 = i;}}if (ret == 0x3f3f3f3f) cout << -1 << endl;else cout << ret << endl;return 0;
}
3.3 总结
- 没有必要真的定义一个字符数组,字符数组的是很珍贵的,数组的意义让你能重复遍历,但是,咱们完全可以一次遍历结束。
- 注意“数组”不要越界。
完
