Cod sursa(job #1731425)

Utilizator tamionvTamio Vesa Nakajima tamionv Data 18 iulie 2016 22:21:50
Problema Lapte Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.38 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;

template <typename T>
int cbin(const int st, int dr, T t){
	// t = fffff...ffffttttt...ttt
	// gaseste primul punct de adevar
	for(int step = 1<<(int)log2(dr-st+1); step; step /= 2){
		if(dr-step >= st && t(dr-step)){
			dr -= step; } }
	return dr; }

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 = cbin(1, 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; }