题意:
有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 ",ans==oo*oo ? -1 : ans); 47 return 0; 48 }