NC208185. AR的背包
描述
AR有n个背包,每一个背包有两个属性,一个为a,一个为b,我们可以移动背包,但是当 时背包就不能移动了。他现在有两个操作:
(1)对于所有可以被操作的背包,让,就是让b的值减少a,花费p点精力。
(2)对于所有可以被操作的背包,执行Swap(a,b),其中Swap(x,y)表示交换x,y的值,花费q点精力。
那么现在问题来了,AR想要花费最少的精力来让所有的背包不能移动,请你告诉他最少的花费为多少。
输入描述
第一行有三个正整数n,p,q。。
接下来n行每行有两个正整数ai,bi表示第个背包的两个属性a和b。。
输出描述
输出一行一个整数,表示你所求得的最小花费。
示例1
输入:
4 9 5 1 7 1 4 6 5 4 2
输出:
23
示例2
输入:
3 500 3 4 6 3 5 8 1
输出:
1000
示例3
输入:
2 1 1000 1 500 2 800
输出:
500
C++11(clang++ 3.9) 解法, 执行用时: 70ms, 内存消耗: 1124K, 提交时间: 2020-06-21 18:29:40
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; struct pt { int a,b; }c[100005]; int n; ll ans,p,q; bool cmp(const pt x,const pt y) { return 1ll*x.a*y.b>1ll*y.a*x.b; //使用叉积可以避免浮点运算 } int main() { scanf("%d%lld%lld",&n,&p,&q); for(int i=1;i<=n;i++) scanf("%d%d",&c[i].a,&c[i].b); sort(c+1,c+n+1,cmp); ans=min(1ll*(c[n].b+c[n].a-1)/c[n].a*p,1ll*(c[1].a+c[1].b-1)/c[1].b*p+q); //特判 for(int i=1;i<n;i++) { pt u=c[i],v=c[i+1]; if(1ll*u.a*v.b==1ll*v.a*u.b) continue; ll nw=0; while(1) { if(u.a>=u.b&&v.a>=v.b) //case 1 { swap(u.a,u.b),swap(v.a,v.b); nw+=q; } else if(u.a<u.b&&v.a<v.b) //case 2 { int ct=min((u.b-1)/u.a,(v.b-1)/v.a); u.b-=ct*u.a,v.b-=ct*v.a; nw+=ct*p; } else //case 3 { if(u.a>=u.b) swap(u,v); ll nw1=0,nw2=0; pt w=u; w.b-=w.a; nw1=q+p+1ll*(w.a+w.b-1)/w.b*p; //case 3.1 if(v.a>v.b) { w=v; swap(w.a,w.b); w.b-=w.a; nw2=p+q*2+1ll*(w.a+w.b-1)/w.b*p; //case 3.2 nw1=min(nw1,nw2); } nw+=nw1; break; } } ans=min(ans,nw); } printf("%lld",ans); return 0; }