PKU 1700 Crossing River

気分転換にPKUの簡単な問題を10問強やった。
三月中に(累計)正解数150問を目標にしよう。


そういえばPKU Judge Onlineの問題を1000問解くと赤コーダーになれるという噂があったような。
頑張って1000問解いて噂の真偽を確かめたいと思うw


面白かった問題の解説を書いておく。

PKU 1700 Crossing River

n人がボート1艇だけを使って川を渡りたい。
ボートは二人乗りで、川を片道渡るのにかかる時間は乗っている人のうち、
遅いほうの(一人の場合はその人の)ボートを漕ぐスピードである。
整数nと、n人それぞれのボートを漕ぐスピードが与えられたとき、全員が川を渡るのにかかる最小の時間はいくらか。


貪欲法で最適解を求めることが可能。
n=1,2,3の時は少し考えれば自明。
n=4以上の時は、「一番遅いほうの二人」を渡す方法のに次の二つの方法が考えられる。
人を漕ぐ速さの順に0,1, ... ,n-2,n-1とすると

  • 一番速い人を使って((0,n-1)行く→0戻る→(0,n-2)行く→0戻る)遅い二人を渡す。
  • 二人を一度に渡す。ボートは1の人が回収する。((0,1)行く→0戻る→(n-1,n-2)行く→1戻る)


これを繰り返すことでn≦3の場合に帰着することができる。

	int t; cin>>t;
	while(t--)
	{
		int n; cin>>n;
		
		int s[n];
		rep(i,n)cin>>s[i];
		sort(s,s+n);
		
		int ans=0;
		while(n>3)
		{
			int a=s[0]*2+s[n-2]+s[n-1];
			int b=s[0]+s[1]*2+s[n-1];
			//dbg(a),dbg(b);
			ans+=min(a,b);
			n-=2;
		}
		if(n==3)ans+=accumulate(s,s+n,0);
		if(n<3)ans+=s[n-1];
		cout<<ans<<endl;
	}

(main関数部分のみ)