sicily 1099 Packing Passengers

/**
**  题意:  求x,y 满足 x*pa+y*pb=n 同时使得 p = x*ca+y*cb的值最小,若有多种可能,则选择最大x值的组合
**  分析:  x*pa+y*pb=n 可以用 线性同余方程 求得各组解: X=x+(pb/q)*t, Y=y-(pa/q)*t 
**   t为整数,显然 X,Y>=0,所以 -x/(pb/q) <= t <= y/(pa/q)
**   欲使 x*ca+y*cb 最小, 注意到 其中 [(pb/q)*t]*ca + [-(pa/q)*t]*cb = (pb*ca-pa*cb)/q*t
**   当pb*ca-pa*cb<0,t应取最大值;
**   当pb*ca-pa*cb>0,t应取最小值;
**   当pb*ca-pa*cb=0,应选择较大的X值,显然 pb/q总是大于0的,所以t 选择最大值,X取得更大值
**   http://zh.wikipedia.org/wiki/%E6%89%A9%E5%B1%95%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E7%AE%97%E6%B3%95
***/

 1 #include<iostream>
 2 #include<cmath>
 3 using namespace std;
 4 
 5 /**
 6 **    扩展欧几里德算法(辗转相除法), x*a+y*b=gcd(a,b)=q 
 7 **/
 8 long long x,y,q;
 9 void extend_eulid(long long a,long long b){
10     if(b==0){
11         x=1;
12         y=0;
13         q=a;    
14     }    
15     else{
16         extend_eulid(b,a%b);
17         //收集辗转相除法中产生的式子,倒回去,可以得到ax+by=gcd(a,b)的整数解
18         long long temp=x;
19         x = y;
20         y = temp-a/b*y;
21     }
22 }
23 int main()
24 {
25     int n,ca,pa,cb,pb,cnt=1;
26     long long upper,lower,t;
27     while(cin>>n&&n){
28         cin>>ca>>pa>>cb>>pb;    
29         extend_eulid(pa,pb);
30         if(n%q!=0)
31             cout<<"Data set "<<cnt++<<": cannot be flown"<<endl;
32         else{
33             //求特解
34             x = x*n/q;
35             y = y*n/q;    
36             upper = (long long)floor((double)y/(pa/q));     //返回小于或者等于指定表达式的最大整数头
37             lower = (long long)ceil((double)-x/(pb/q));     //返回大于或者等于指定表达式的最小整数头   
38             t = pb*ca-pa*cb<=0 ? upper : lower;    
39             cout<< "Data set "<<cnt++<<": "<<x+(pb/q)*t<<" aircraft A, "<<y-(pa/q)*t<<" aircraft B"<<endl;
40         }
41     }
42     return 0;
43 }

 

转载于:https://www.cnblogs.com/renaissance/p/3511347.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值