cdcq

梦幻小鱼干

导航

【SEERC 2019】E - Life Transfer

题意:

有n个人去旅游,可以选择开车或者骑摩的,一辆车带m个人(含司机),要求司机年龄大于lc,租金pc,一辆摩的只能带一个人(司机自己),要求司机年龄大于lm,租金pm

然后你还可以玩一个生命游戏(□..□)

每次花t块钱,把一个人的年龄续给另一个人,要求1.年龄不能小于1,2.对每个人最多用d次(包括给的人和接的人)

现在告诉你所有人的年龄ai,问你最少花费把所有人都带走,如果做不到输出-1

 

此题需要注意到一个关键性质:

如果枚举开车的人,那么骑车的人和坐车的人都固定了

我想到了枚举开车的人,但是没深入的往下研究,没发现骑车的人也固定了,这个看题解才发现

此外本题代码不太好实现,比较绕脑,有一些些小细节

但是这道题我看题解后还自闭了一下午,为什么呢

因为一辆车带m个人,不含司机啊啊啊啊啊啊啊啊

一个司机带m-1个人

 

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 using ll=long long int;
 6 const ll oo=1000000007;
 7 int n,m;
 8 ll lc,pc,lm,pm;
 9 ll c,d;
10 ll a[110000];
11 ll s[110000];
12 ll g[110000];
13 int main(){
14     scanf("%d%d",&n,&m);
15     scanf("%lld%lld%lld%lld",&lc,&pc,&lm,&pm);
16     scanf("%lld%lld",&c,&d);
17     for(int i=1;i<=n;++i)  scanf("%lld",&a[i]);
18     sort(a+1,a+n+1);
19     for(int i=n;i>=1;--i){
20         if(a[i]>=lm)  s[i]=s[i+1];
21         else if(a[i]>=lm-d)  s[i]=s[i+1]+(lm-a[i]);
22         else  s[i]=s[i+1]+oo;
23         if(a[i]>=lm)  g[i]=g[i+1]+min(d,a[i]-lm);
24         else  g[i]=g[i+1];
25     }
26     int l=1,r=n;
27     ll ans=oo*oo;
28     ll bwl1=0;
29     ll bwl2=0;
30     for(;r>l && lc-a[r]<=d;--r){
31         if(a[r]>=lc)  bwl1+=min(d,a[r]-lc);
32         else  bwl2+=lc-a[r];
33         for(;l<r && l<=(n-r+1)*(m-1);++l)
34             bwl1+=min(d,a[l]-1);
35         if(l<r && bwl2+s[l]-s[r]<=bwl1+g[l]-g[r])
36             ans=min(ans,(bwl2+s[l]-s[r])*c+(n-r+1)*pc+(r-l)*pm);
37         if(l>=r)  break;  //防止r再减少
38     }
39     if(s[1]<=g[1])  ans=min(ans,s[1]*c+n*pm);
40     if(n==1){
41         if(a[1]>=lm)  ans=min(ans,pm);
42     }
43     if(l>=r){
44         if(bwl1>=bwl2)  ans=min(ans,bwl2*c+(n-r+1)*pc);
45     }
46     printf("%lld\n",ans==oo*oo ? -1 : ans);
47     return 0;
48 }
View Code

 

posted on 2020-11-26 20:11  cdcq  阅读(212)  评论(0编辑  收藏  举报