码上掘金

124 阅读1分钟

题目三 BFS

一个点只能扩散3个点,对于这三个点(可以去重,减少队列中点的个数)。

  1. idx + 1 这种情况,考虑这种情况,超过目的地还需要向右走吗?
  2. idx - 1 , (n / 2)-1这样的位置最好的走法是,左走一步然后大胯步,所以这种没有优化。
  3. 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;
}