2018美团CodeM编程大赛 Round A Problem 2 下棋 贪心

Posted zhenghanghu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018美团CodeM编程大赛 Round A Problem 2 下棋 贪心相关的知识,希望对你有一定的参考价值。

技术分享图片

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

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

 

 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上,但自己编了几个数据都过了。



以上是关于2018美团CodeM编程大赛 Round A Problem 2 下棋 贪心的主要内容,如果未能解决你的问题,请参考以下文章

美团点评CodeM编程大赛;fastjson 1.2.33 发布;“闪电立方”一次可传100T数据

CodeM 2017美团点评编程大赛资格赛

CodeM美团点评编程大赛初赛B轮 黑白树DFS深搜+暴力

Loj #6164. 「美团 CodeM 初赛 Round A」数列互质

美团2017年CodeM大赛-初赛B轮 黑白树 (树形dp)

组委会正在为美团点评CodeM大赛的决赛设计新赛制