soj 1099. Packing Passengers

题目大意:题目有多个测试样例。每个测试样例第一行为需要乘坐飞机的乘客总数n,第二行为使用一架飞机A的代价costA(简写成ca)和能够容纳的乘客数passengersA(简写成pa),第三行为使用一架飞机B的代价costB(简写成cb)和能够容纳的乘客数passengersB(简写成pb).对每个测试样例求使用飞机A的数量x和飞机B的数量y的值,使得刚好能够容纳n个乘客,并且总代价最小。当存在多组(x, y)满足条件时,选择x最大的一组。当n为0时,输入结束。

解题思路:由题目得 pa * x + pb * y = n。根据裴蜀定理可得,若gcd(pa, pb)能够整除n,则存在整数对(x, y)满足条件(使用扩展欧几里得算法能够求得),反之则不存在解。x *= n / gcd(pa, pb), y *= n / gcd(pa, pb), 能够获得一组解。

通解X = x + pb / gcd(pa, pb) * t, Y = y - pb / gcd(pa, pb) * t.

运用题目条件:

由于X,Y >= 0,所以 (-x) / (pb/gcd(pa, pb))  <= t <= y / (pb/ gcd(pa, pb)).

此时,若确定t的值,即可确定X,Y的解。

根据题目条件:要使总代价最小,首选性价比最高的飞机。

1.若ca * pb <= cb * pa,则飞机A的性价比最高或者两者性价比相同,选择飞机A越多越好,即t越大越好。t取最大值。PS:最大值的下限。

2.若ca * pb > cb * pa, 则飞机B的性价比最高,选择飞机B越多越好,即t越小越好。t取最小值。PS:最小值的上限。

 

代码如下:

 1 #include <cstdio>
 2 #include <cmath>
 3 
 4 typedef long long LL;
 5 
 6 template <typename T>
 7 T gcdEx(T a, T b, T * x, T *y) {
 8     if (b == 0) {
 9         *x = 1, *y = 0;
10         return a;
11     } else {
12         T r = gcdEx(b, a % b, x, y);
13         T t = *x;
14         *x = *y;
15         *y = t - a / b * *y;
16         return r;
17     }
18 }
19 template <typename LL > LL gcdEx(LL a, LL b, LL *x, LL *y);
20 
21 int main() {
22     LL n, ca, cb, pa, pb;
23     int N = 0;
24     while (++N, scanf("%lld", &n), n) {
25         scanf("%lld%lld%lld%lld", &ca, &pa, &cb, &pb);
26         LL x, y;
27         LL gcd = gcdEx(pa, pb, &x, &y);
28 
29         if (n % gcd != 0) {
30             printf("Data set %d: cannot be flown\n", N);
31         } else {
32             x *= n / gcd, y *= n / gcd;
33 
34             LL t;
35             if (ca * pb <= cb * pa)
36                 t = floor((y + 0.0) / (pa / gcd));
37             else
38                 t = ceil((-x + 0.0) / (pb / gcd));
39 
40             x += pb / gcd * t;
41             y -= pa / gcd * t;
42             printf("Data set %d: %lld aircraft A, %lld aircraft B\n", N, x, y);
43         }
44     }
45     return 0;
46 }

 

Reference :

posted @ 2015-12-12 15:25  MchCyLh  阅读(278)  评论(0编辑  收藏  举报