BZOJ 2151 2151: 种树 (贪心+堆)
Posted konjak魔芋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2151 2151: 种树 (贪心+堆)相关的知识,希望对你有一定的参考价值。
2151: 种树
Description
A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。
Input
输入的第一行包含两个正整数n、m。第二行n个整数Ai。
Output
输出一个整数,表示最佳植树方案可以得到的美观度。如果无解输出“Error!”,不包含引号。
Sample Input
【样例输入1】
7 3
1 2 3 4 5 6 7
【样例输入2】
7 4
1 2 3 4 5 6 7
Sample Output
【样例输出1】
15
【样例输出2】
Error!
【数据规模】
对于全部数据:m<=n;
-1000<=Ai<=1000
N的大小对于不同数据有所不同:
数据编号 N的大小 数据编号 N的大小
1 30 11 200
2 35 12 2007
3 40 13 2008
4 45 14 2009
5 50 15 2010
6 55 16 2011
7 60 17 2012
8 65 18 199999
9 200 19 199999
10 200 20 200000
HINT
Source
【分析】
应该是一种很经典的贪心吧【为什么我不会。。。
贪心思想:每次选择合法的最大的一个
如果这是这样当然是错的,要给他一点后悔的机会【感觉有点网络流的思想啊
假设你选的最大的一个是x2,x1、x3和他相邻,其实可能你的最优方案是不选x2,而选x1、x3【但是一定两个都选,不可能只选x1或x3,因为x2最大
所以我们把x1 x2 x3 都删掉,插入一个新结点,贡献为x1+x3-x2,如果选了他,说明你反悔了,决定选x1、x3而放弃x2。
【思路就是这么巧妙简单啊~~
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 #include<vector> 9 using namespace std; 10 #define Maxn 200010 11 12 struct node 13 { 14 int x,id; 15 friend bool operator < (node x,node y) 16 { 17 return x.x<y.x; 18 } 19 }; 20 21 priority_queue<node > q; 22 23 bool mark[2*Maxn]; 24 int lt[2*Maxn],nt[2*Maxn],w[2*Maxn]; 25 26 int main() 27 { 28 int n,m; 29 scanf("%d%d",&n,&m); 30 for(int i=0;i<n;i++) scanf("%d",&w[i]); 31 32 if(m>n/2) printf("Error!\\n"); 33 else 34 { 35 int ans=0,cnt=n-1; 36 while(!q.empty()) q.pop(); 37 for(int i=0;i<n;i++) 38 { 39 node nw; 40 nw.x=w[i];nw.id=i; 41 q.push(nw); 42 } 43 for(int i=0;i<n;i++) nt[i]=(i+1)%n; 44 for(int i=0;i<n;i++) lt[i]=(i-1+n)%n; 45 memset(mark,0,sizeof(mark)); 46 for(int i=1;i<=m;i++) 47 { 48 while(mark[q.top().id]) q.pop(); 49 node nw=q.top();q.pop(); 50 ans+=nw.x; 51 cnt++; 52 mark[lt[nw.id]]=mark[nt[nw.id]]=1; 53 nt[lt[lt[nw.id]]]=cnt;lt[nt[nt[nw.id]]]=cnt; 54 nt[cnt]=nt[nt[nw.id]];lt[cnt]=lt[lt[nw.id]]; 55 node xx; 56 w[cnt]=w[lt[nw.id]]+w[nt[nw.id]]-nw.x; 57 xx.x=w[cnt];xx.id=cnt; 58 q.push(xx); 59 } 60 printf("%d\\n",ans); 61 } 62 return 0; 63 }
2017-01-13 20:32:36
以上是关于BZOJ 2151 2151: 种树 (贪心+堆)的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 2151 种树(可反悔贪心,链表)BZOJ千题计划就图一乐