列表

详情


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;
}

上一题