poj2142-The Balance(擴展歐幾里德算法)


一,題意:
  有兩個類型的砝碼,質量分別為a,b;現在要求稱出質量為d的物品,
  要用多少a砝碼(x)和多少b砝碼(y),使得(x+y)最小。(注意:砝碼位置有左右之分)。
二,思路:
  1,砝碼有左右位置之分,應對比兩種情況
    i,a左b右,得出方程 ax1 - by1 = d ;
    ii,b左a右,得出方程 bx2 - ay2 = d 。
  2,利用擴展歐幾里德算法,解出(x1,y1)、(x2,y2),並求出最小x1和x2,以及相對應的y1,y2。
  3,輸出x1+y1和x2+y2 中的最小值。
三,步驟:
  1,由題意得出兩個方程
    i,ax1 - by1 = d ;
    ii,bx2 - ay2 = d 。
  2,代入算法,解出兩個方程的解(x1,y1)、(x2,y2),並求出最小x1和x2,以及相對應的y1,y2.
    (詳細步驟請參照本博客poj1061或者poj2115)。
  3, 判斷步驟
    i,x1+y1最小時,輸出x1,y1
    ii,x2+y2最小時,輸出y2,x2。 *此處為y2在前面輸出,因為x2+y2最小時,第一個輸入的a對應的是y2。

 1 #include<iostream>
 2 #include<cmath>
 3 using namespace std;  4 
 5 void exgcd(int a,int b,int& g,int& x,int& y){  //int& a 是定義一個存放整形變量a的地址
 6     if(!b){ g = a ; x = 1 ; y = 0;}                   // g用來存儲gcd(a,b)的值 
 7     else { exgcd(b , a%b , g , y , x) ; y -= x * (a/b) ; }  8 }  9 
10 void work(int a , int b , int d ,int& g , int& x , int& y){ 11     exgcd(a,b,g,x,y);      //此處的x,y接收 ax+by=gcd(a,b)的值 
12     x *= d/g;             //求ax+by=c 的解x 13 // y *= d/g; //求ax+by=c 的解y 
14     int t = b/g; 15     x = (x%t + t) % t;       //求出最小非負整數 
16     y = abs( (a*x - d) / b);  //求相對應的y,取絕對值是為了當左邊砝碼數 x 為零的時候,得出來的 y 是正整數。 
17 /* //以下是先求y再求對應的x 。 18  int t = a/g; 19  y = (y%t + t) % t; 20  x = abs( (d + b*y) / a); 21 */
22 } 23 
24 int main(){ 25     int a,b,d,g,x1,x2,y1,y2; 26     while(cin>>a>>b>>d){ 27         if(a==0&&b==0&&d==0)break; 28  work(a,b,d,g,x1,y1); 29  work(b,a,d,g,x2,y2); 30         if( x1+y1 < x2+y2 ) 31             cout<<x1<<" "<<y1<<endl; 32         else
33             cout<<y2<<" "<<x2<<endl;   //(注意順序)
34  } 35     return 0; 36 }
View Code

   版權聲明:本文為博主原創文章,未經博主允許不得轉載。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM