読者です 読者をやめる 読者になる 読者になる

C++競プロ学習日記(仮)

( 学習記録であり解説Blogではないです )

Round #326 A. Duff and Meat|Codeforces

Codeforces コード 競プロ 競プロメモ STL 貪欲

Problem - A - Codeforces を解きました。
ktnさん適度な問題をいくつかpick upして頂いたのですがそのうちの1問です。
(適度な問題:私のレベルに対しての適度)

Duffちゃんが必要な肉の量/day と コスト/day がN日分与えられるので、
必要な肉を買う最小コストをprintすると言うもの(適当)
つまり特売日に肉を買いだめて行くスタイル。

#include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(n); i++)
using namespace std;
int main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);

	int N;
	cin >> N;

	vector<int> amount(N),cost(N);
	REP( i, N )
	{
		cin >> amount[i] >> cost[i];
	}
	int MIN = cost.front(),res{};
	REP( i, N )
	{
		MIN = min( MIN, cost[i] );
		res += amount[i] * MIN;
	}
	cout << res << endl;
	return 0;
}

最終的に修正したコード。
最初、min値の更新を if に入れたり変なことをしていた...。
でも簡単な貪欲問題解けて良かった!
その時々で最善な選択をしていく、が貪欲と呼ばれる解法っぽいです。

#include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(n); i++)
using namespace std;
int main()
{
	cin.tie(0);
	ios::sync_with_stdio(false);

	int N;
	cin >> N;

	vector<int> amount(N), cost(N);
	REP( i, N )
	{
		cin >> amount[i] >> cost[i];
	}
	vector<int> total;
	partial_sum( cost.begin(), cost.end(), back_inserter(total),
		[]( int MIN, int cost ){ return min( MIN, cost ); } );
	cout << inner_product( amount.begin(), amount.end(), total.begin(), 0 ) << endl;
	return 0;
}

次にプロのコードからの学び。
使った事のないSTLが2つも出て来たので学習的でした。
std::partial_sum は要素の部分和が取れます*1
が、その機能を利用して第四引数のラムダでmin値をreturnしています。
(※部分和を取る訳ではない / ここの理解が難しかった...)

「先頭から各位置までの要素全ての和」の代わりに
「先頭から各位置までの要素全ての min」を求めている

その後、要素間を乗算し加算されたtotalを返してくれる、
std::inner_product*2 を使って計算結果を得ます。

STLを使ったこんな書き方も出来るんだー...という学びでした。

(難しかった....)