Cod sursa(job #1732736)

Utilizator tamionvTamio Vesa Nakajima tamionv Data 22 iulie 2016 14:43:15
Problema Lapte Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.46 kb
/*
   trebuie sa gasim ai, bi astfel incat:
   max(ta * ai + tb * bi) sa fie minim
   sum(ai) >= l && sum(bi) >= l

   facand cbin, trebuie sa vedem daca exista un sir de numere ai, bi a.i.
   max(ta * ai + tb * bi) <= t && sum(ai) >= l && sum(bi) >= l

   fixand pentru fiecare om in parte ai, putem considera cateva perecchi valide.
   Odata fixat t, atunci putem alege, pentru fiecare om in parte, un numar de
   perechi (ai, bi). facem dinamica d[i][j] = cantitatea de lapte de tip b
   buna, daca luam primele i persoane, cu j lapte a.
*/

#include <bits/stdc++.h>
using namespace std;

struct int_it : iterator<random_access_iterator_tag, int>{
	int x;
	int_it(): x(0){}
	int_it(const int xx): x(xx){}
	int_it operator++(){ ++x; return *this; }
	int_it operator+=(const int d){ x += d; return *this; }
	int operator-(const int_it& rhs){ return x - rhs.x; }
	int operator*(){ return x; } };

bool verif_posibil(const int n, const int t, const int l,
		const vector<int>& ta, const vector<int>& tb){
	vector<int> d_cur(l+1, -1000 * 1000 * 1000), d_prev(l+1, 0);
	d_cur[0] = 0;
	for(int i = 0; i < n; ++i){
		copy(begin(d_cur), end(d_cur), begin(d_prev));
		for(int a = 0; a <= l && a * ta[i] <= t; ++a){
			const int b = (t - a * ta[i]) / tb[i];
			for(int j = l-a, k = l; j >= 0; --j, --k){
				d_cur[k] = max(d_cur[k], d_prev[j] + b); } } }
	return d_cur[l] >= l; }

vector<pair<int, int>> build_sol(const int n, const int t, const int l,
		const vector<int>& ta, const vector<int>& tb){
	vector<vector<int>> d(n+1, vector<int>(l+1, -1000 * 1000 * 1000));
	vector<vector<pair<int, int>>> prev(n+1, vector<pair<int,int>>(l+1, make_pair(-1, -1)));

	d[0][0] = 0;

	for(int i = 0; i < n; ++i){
		for(int a = 0; a <= l && a * ta[i] <= t; ++a){
			const int b = (t - a * ta[i]) / tb[i];
			for(int j = l-a, k = l; j >= 0; --j, --k){
				if(d[i+1][k] < d[i][j]+b){
					d[i+1][k] = d[i][j]+b;
					prev[i+1][k] = make_pair(a, b); } } } }
	vector<pair<int, int>> rez(n);
	for(int i = n, j = l; i > 0; --i){
		rez[i-1] = prev[i][j];
		j -= rez[i-1].first; }

	return rez; }


int main(){
	ifstream f("lapte.in");
	ofstream g("lapte.out");

	int n, l;
	f >> n >> l;

	vector<int> ta(n), tb(n);
	for(int i = 0; i < n; ++i){
		f >> ta[i] >> tb[i]; }

	const int rez = *partition_point(int_it(1), int_it(101), [&](const int t){
			return !verif_posibil(n, t, l, ta, tb); });
	const auto plan = build_sol(n, rez, l, ta, tb);

	g << rez << '\n';
	for(const auto p : plan){
		g << p.first << ' ' << p.second << '\n'; }

	return 0; }