F.ビールマラソン(2ポイント+反復+貪欲)

ここに画像の説明を挿入ここに画像の説明を挿入ここに画像の説明を挿入
この質問の意味は理解しやすいですが、書くのは簡単ではありません。
質問の意味:初期ブースn個の位置を与えると、2つのブースの間の距離がk個になるように、これらのブースを移動、最小移動距離の和を見つけるには、
私はまた、溶液を読んだ後に、この問題を理解し、
なぜなら最終的にはいつも同じ距離に移動しませんか?
意味は(開始点がa [0]、n = 4であると仮定します):
ここに画像の説明を挿入
それからそれは最後に上記のスタイルに移動します;
それから私たちはタイトルによって与えられた各座標を上の対応する位置に渡すことができますか?マイナス;
たとえば、開始点が1、2、3、4(kは1)であり、タイトルで指定された初期座標が0、1、2、5であると仮定します。
次に、0-1、1 -2、2 -3,5-4;結果は-1、-1、-1,1;それは正しいですか?
それで問題を見つけることができます;開始点が1であると仮定すると、与えられた位置タイトルのは最終的に1、2、3、4の位置に変更されます;
したがって、上記の差の絶対値の合計が合計移動距離であるかどうかを確認できます;これは私が答えたときだけの答えだからです開始点が1時であると仮定しますが、これと最小値が必要です。実際、開始点は他の座標にあると想定できますが、最終的にはすべて次の形式になり
ここに画像の説明を挿入
ます。開始点を分割できますか?
ちなみにアイデアはここにありますが、開始間隔はどのくらいですか?
この質問は少し形而上学的ですが、なぜそれを渡すために2番目のパーティションを1e12に開いて、反復法を使用したためです;
実際、この質問のアイデアはすでに理解されています、それは出発点を列挙することです、そして最小の答えを記録し続けます;
実際、この質問はホワイトブックの最大値と最小値が同じです(2ポイント+貪欲);しかし、この問題にはまだ繰り返しがあります。知識の増加。
詳細については、コードを参照してください
。ACコード:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,k;
ll a[1000010];
ll sum(ll d){
    
    //这个函数就是用来计算初始值和最终值的差值的和,也就是最终移动的距离
	ll res=0;
	for(int i=0;i<n;i++){
    
    
		  res+=abs(a[i]-d);
		  d+=k;
	}
	return res;
}
int main(){
    
    
	cin>>n>>k;
	for(ll i=0;i<n;i++)cin>>a[i];
	sort(a,a+n);//题目输入并没有顺序,所以需要排序
	ll l=-1e12,r=1e12;//二分起点坐标
	ll t1,t2;
	ll ans=1e18;//记录答案
	for(ll i=0;i<100;i++){
    
    
		ll L=l+(r-l)/3,R=r-(r-l)/3;//这里为什么不用L=l,R=r?就是迭代的知识,只不过这点确实不好想
		  t1=sum(L);
		  t2=sum(R);
		  if(t1<t2){
    
    
		  	 r=R;
		  }else {
    
    
		     l=L;
		  }
		  ans=min(ans,min(t1,t2));
		  //cout<<t1<<t2<<endl;
	}
	cout<<ans<<endl;
	return 0;
}

おすすめ

転載: blog.csdn.net/qq_44555205/article/details/104450507