zoukankan      html  css  js  c++  java
  • 2018美团CodeM编程大赛 Round A Problem 2 下棋 【贪心】

    应该一眼看出来是贪心题,然后想最优解是什么。正确的贪心策略是【原棋盘上每个位置的棋子】都往最近的左边【目标棋盘上棋子】移动,如果左边没有棋子了那就闲置最后处理,如果目标棋盘在该位置上也有棋子,那就算距离为0(最近)。最后处理的话,棋盘上的局面应该是所有的棋子都得往右移,这样的话怎么移都无所谓了,朴素的把放过去。

    模拟的时候难度在于通过upper bound找到离该位置最近左的位置,所以复杂度是O(NlogN);如果朴素的遍历数组找最近左需要N复杂度,整体n^2就过不了了。

     对于upper_bound来说,返回的是被查序列中第一个大于查找值的指针,也就是返回指向被查值>查找值的最小指针,lower_bound则是返回的是被查序列中第一个大于等于查找值的指针,也就是返回指向被查值>=查找值的最小指针。 【引用自 https://blog.csdn.net/u011008379/article/details/50725670 】

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<map>
     4 #include<vector>
     5 using namespace std;
     6 
     7 int board[100005];
     8 vector<int> va;
     9 map<int,int> m;
    10 long long ans;
    11 //贪心策略
    12 //每个都向自己最近的左边的棋子移动
    13 int main(){
    14     int n; cin>>n;
    15     for(int i=1;i<=n;i++) cin>>board[i];
    16     for(int i=1;i<=n;i++){
    17         int x; cin>>x;
    18         if(x){//这个位置上有棋子
    19             va.push_back(i);
    20             m[i]=x;
    21         }
    22     }
    23     
    24     for(int i=1;i<=n;i++){
    25         while(1){
    26             vector<int>::iterator index = upper_bound(va.begin(),va.end(),i);/* index指向第一个大于i的元素 */
    27             //如果没有比i还大的,返回begin()
    28             if(index==va.begin()) break;//目标盘左边没有棋子了 
    29             index--; 
    30             if( m[ *index ]>board[i] ) {
    31                 ans+=(i-(*index) )*board[i];
    32                 m[*index]-=board[i];
    33                 board[i]=0;
    34                 break;
    35             }
    36             if( m[ *index ]==board[i] ){
    37                 ans+=(i-(*index))*board[i];
    38                 va.erase(index);
    39                 board[i]=0;
    40                 break;
    41             }
    42             if( m[ *index]<board[i]){
    43                 ans+=(i-(*index))*m[ *index];
    44                 va.erase(index);
    45                 board[i]-=m[*index];
    46             }
    47         }
    48     }
    49     
    50     for(int i=1;i<=n;i++){
    51         if(board[i]==0) continue;
    52         while(1){
    53             if( m[ va[0] ]>board[i] ) {
    54                 ans+=(i+va[0]-2)*board[i];
    55                 m[ va[0] ]-=board[i];
    56                 break;
    57             }
    58             if( m[ va[0] ]== board[i] ){
    59                 ans+=(i+va[0]-2)*board[i];
    60                 va.erase(va.begin());
    61                 break;
    62             }
    63             if( m[ va[0] ]<board[i]){
    64                 ans+=(i+va[0]-2)*m[ va[0] ];
    65                 va.erase(va.begin());
    66                 board[i]-=m[ va[0] ];
    67             }
    68         }
    69     }
    70     
    71     cout<<ans<<endl;
    72     
    73     return 0;
    74 }

    没有提交在美团的oj上,但自己编了几个数据都过了。

  • 相关阅读:
    沿着河边走,环城60公里
    与客家土楼的约会(叶剑英故居福建)
    与客家土楼的约会(增城河源)
    与客家土楼的约会(东源龙川)
    C#几个经常犯错误
    C# 获取当前路径方法
    C# Stopwatch与TimeSpan详解
    话说程序员成熟的标志
    C#开源项目介绍
    C#各种加密算法的研究
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9162910.html
Copyright © 2011-2022 走看看