题目三 BFS
一个点只能扩散3个点,对于这三个点(可以去重,减少队列中点的个数)。
- idx + 1 这种情况,考虑这种情况,超过目的地还需要向右走吗?
- idx - 1 , (n / 2)-1这样的位置最好的走法是,左走一步然后大胯步,所以这种没有优化。
- idx * 2, 目的地是 k,当前点是 idx, 假设 idx > n / 2, 那么 idx * 2 > y ,我们走到y还需走 y - idx 步,有 idx * 2 - y <= y -idx -> idx <= (y * 2) / 3,这个一个小优化。
int main(){
int n,k;
cin >> n >> k;
map<int,int> mp;
// 第几次,跳在哪
queue<pair<int,int>> q;
q.push({0,n});
while(q.size()){
auto t = q.front(); q.pop();
auto idx = t.second, time = t.first;
if(idx == k){
// 第一次到达 时间肯定是最短的
cout << time << endl;
break;
}
// x + 1
if(mp[idx + 1] == 0 && idx + 1<= k){
q.push({time + 1,idx + 1});
}
if(mp[idx - 1] == 0){
q.push({time + 1,idx - 1});
}
// 2x - y <= y - x -> x <= y * 2/ 3(y=k)
if(mp[idx * 2] == 0 && idx <= (k * 2 + 2) / 3){
q.push({time + 1,idx * 2});
}
}
return 0;
}
题目4 接雨水
考虑当前点的贡献,左边最大和右边最大的最小值 - 当前高度(需要将它包围,所以需要最大)。 5 3 4 -> 4 - 3 = 1 4 5 6 -> 4 - 5 ? 所以我们应该将当前点也算上。
int main(){
vector<int> a;
int b;
while(cin >> b){
a.push_back(b);
cout << a.size()<<endl;
}
int n = a.size();
vector<int> pre(n ,-1),suf(n ,-1);
pre[0] = a[0];
for (int i = 1; i < n; ++i) pre[i] = max(pre[i - 1], a[i]);
suf[ n - 1]= a.back();
for (int i = n - 2; i >= 0; i--) suf[i] = max(suf[i + 1], a[i]);
int ans = 0;
for(int i = 1;i < n - 1;i ++){
ans += min(pre[i],suf[i]) - a[i];//每个点的贡献
}
cout << ans;
return 0;
}