1. 程式人生 > 其它 >【拓展歐幾里得】渡河(2022.5.21)

【拓展歐幾里得】渡河(2022.5.21)

上題目!

題目

2.1 題目描述

現在有 N 名遊客需要渡河到對岸,但是島上只有兩艘船,第一艘船可以容納 n1 名遊客,第二艘船可以容納 n2 名遊客,為了不浪費位置,船長要求每次必須坐滿才能出發。現在已知使用第一艘船運輸一趟需要花費 c1,使用第二艘船運輸一趟需要花費 c2,問最小總花費。

2.2 輸入格式

第一行為一個整數 T,表示資料組數;
接下來T 行,每行五個整數 N, n1, c1, n2, c2,含義如題意所述。

2.3 輸出格式

輸出T 行對應T 組資料的答案,每行輸出兩個整數m1 和 m2 分別表示總花費最小時第
一艘船和第二艘船的運輸趟數,若無解則輸出“No solution”。當有解時,保證最優解唯一。

2.4 樣例輸入

2 
43 3 1 4 2 
40 9 5 12 5 

2.5 樣例輸出

13 1 
No solution 

2.6 資料範圍與約定

對於前30%的資料 N≤100;
對於100%的資料,1≤T≤10000,1≤N,c1,c2,n1,n2≤2*109。

解思

拓歐跑一遍求最優通解(x,y大於零且價值最大的船對應的次數最大)即可

上程式碼

點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){
	int f=1,j=0;char w=getchar();
	while(w>'9'||w<'0'){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(w>='0'&&w<='9'){
		j=(j<<3)+(j<<1)+w-'0';
		w=getchar();
	}
	return f*j;
}
int t;
int extend_gcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1;y=0;
		return a;
	}
	int d=extend_gcd(b,a%b,x,y);
	int tmp=x;
	x=y;
	y=tmp-(a/b)*y;
	return d;
}
int n,x,y,c1,c2,a,b;
signed main(){
	//freopen("river.in","r",stdin);
	//freopen("river.out","w",stdout);
	t=read();
	while(t--){
		int use=0;
		n=read();a=read();c1=read();b=read();c2=read();
		if(a*c2<=b*c1)swap(a,b),use=1;
		int d=extend_gcd(a,b,x,y);
		if(n%d!=0){
			printf("No solution\n");
			continue;
		}
		x*=n/d;y*=n/d;
		int tag=a/d,k;
		if(y<0){
			k=abs(y)/tag;
			if(y+k*tag<0)k++;
			y+=tag*k;
			x-=tag*b/a*k;
		}
		else{
			k=y/tag;
			y-=tag*k;
			x+=tag*b/a*k;
		}
		if(x<0||y<0)printf("No solution\n");
		else if(!use)printf("%lld %lld\n",x,y);
		else printf("%lld %lld\n",y,x);
	}
	return 0;
}
/*
2
43 3 1 4 2
40 9 5 12 5
1
1 5 1000 7 1
*/