2020qbxt D1T3 停车

嗯...

 

题目:

【问题描述】

市中心有一个环形的停车场,编号1到n,现在有m个车要停,停在每个位置会有不同的费用。为了方便,不允许两辆车停在相邻的位置,请问停好所有车的最小花费是多少?

【输入格式】

第一行包含两个正整数n, m,保证n>=2m-1

第二行包含n个正整数,表示停在i位置的费用

【输出格式】

输出一个整数,表示停好所有车的最小花费是多少

【样例输入】

7 3

1 2 3 4 5 6 7

【样例输出】

9

【样例说明】

停在1 3 5

【数据规模与约定】

20% n<=10

40% n<=100

60% n<=1000

100% n<=100000 ai<=10000

 

分析:

这道题我们首先会考虑贪心。如果没有限制,只需要从小到大贪心即可。由于有了限制,考虑设计能够撤销之前操作。

考虑一个性质的证明:

如果有1 2 3 三个数中选择,如果不选2,那么一定会选1和3。这样的话如果选了2,删除1、3两个节点,把2的权值更改成a[1]+a[3]-a[2],相当于把2修改成了1和3。

优先队列优化贪心可以做到O(nlogn),每次处理后用链表来删除。

 

AC代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<queue>
 4 #define pa pair<int,int>
 5 using namespace std;
 6 
 7 int n,m,ans;
 8 int vis[10005],a[10005],L[10005],R[10005];
 9 priority_queue<pa,vector<pa>,greater<pa> >q;
10 
11 inline void del(int x){
12     vis[x]=1;
13     R[L[x]]=R[x];
14     L[R[x]]=L[x];
15 }
16 
17 int main(){
18     scanf("%d%d",&n,&m);
19     for(int i=1;i<=n;i++){
20         scanf("%d",&a[i]);
21         L[i]=(i==1)?n:i-1;
22         R[i]=(i==n)?1:i+1;
23         q.push(pa(a[i],i));
24     }
25     while(m--){
26         while(vis[q.top().second]) q.pop();
27         int x=q.top().second; q.pop();
28         ans+=a[x];
29         a[x]=a[L[x]]+a[R[x]]-a[x];
30         del(L[x]); del(R[x]);
31         q.push(pa(a[x],x));
32     }
33     printf("%d\n",ans);
34     return 0;
35 }
AC代码
posted @ 2020-01-16 22:12  dfydn  阅读(113)  评论(0编辑  收藏  举报